{"id":47713199,"url":"https://github.com/mateof/mock-server","last_synced_at":"2026-04-02T18:42:24.069Z","repository":{"id":336297048,"uuid":"1126837166","full_name":"mateof/mock-server","owner":"mateof","description":"A powerful mock server","archived":false,"fork":false,"pushed_at":"2026-03-20T16:31:18.000Z","size":2263,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-21T07:59:47.058Z","etag":null,"topics":["mock","mock-server","mocking","open-api","server","stubs"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mateof.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-02T17:04:08.000Z","updated_at":"2026-03-20T16:31:23.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/mateof/mock-server","commit_stats":null,"previous_names":["mateof/mock-server"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mateof/mock-server","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mateof%2Fmock-server","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mateof%2Fmock-server/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mateof%2Fmock-server/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mateof%2Fmock-server/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mateof","download_url":"https://codeload.github.com/mateof/mock-server/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mateof%2Fmock-server/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31313217,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-02T12:59:32.332Z","status":"ssl_error","status_checked_at":"2026-04-02T12:54:48.875Z","response_time":89,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["mock","mock-server","mocking","open-api","server","stubs"],"created_at":"2026-04-02T18:42:23.570Z","updated_at":"2026-04-02T18:42:24.062Z","avatar_url":"https://github.com/mateof.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# MockServer\n\nA powerful HTTP mocking and proxying application built with Express.js and Node.js. It provides a web-based interface for configuring dynamic mock routes, managing HTTP requests, and proxying traffic to backend servers.\n\n\u003cimg width=\"2974\" height=\"1459\" alt=\"image\" src=\"https://github.com/user-attachments/assets/f40d6512-2237-4898-9741-1d1b9c335bce\" /\u003e\n\n\n## Features\n\n### Route Management\n- Create, read, update, delete mock routes\n- Support for multiple HTTP methods (GET, POST, PUT, DELETE, PATCH, OPTIONS, HEAD, ANY)\n- Regex pattern matching for advanced route matching\n- Route prioritization with automatic order management\n- Enable/disable routes without deletion\n\n### Response Types\n| Type | Description |\n|------|-------------|\n| **JSON** | JSON object responses |\n| **XML** | XML document responses |\n| **SOAP** | SOAP envelope responses |\n| **Text** | Plain text responses |\n| **HTML** | HTML document responses |\n| **Page** | EJS template rendering |\n| **File** | Upload and serve files (up to 50MB) |\n| **Empty** | Empty 204 responses |\n| **GraphQL** | GraphQL endpoint with per-operation mock/proxy support |\n| **WebSocket** | WebSocket endpoint with configurable message handlers |\n| **Proxy** | Forward requests to backend servers |\n| **Redirect** | HTTP 301 redirects |\n\n### Advanced Features\n\n- **Active Wait Mode** - Block requests until manually triggered from UI\n  - Allows testing timeout scenarios\n  - Supports custom response overrides before release\n\n- **Regex Route Matching** - Test routes with regex patterns in UI\n  - Validation with test URL\n  - Separate path extraction for proxies\n\n- **Custom Headers** - Add, modify, or remove response headers\n  - Array-based configuration: `{action: \"set\"|\"remove\", name, value}`\n  - Applied to both mock and proxy responses\n\n- **Request/Response Logging** - Real-time terminal-style console\n  - Color-coded by type\n  - Detailed proxy logs with collapsible request/response bodies\n  - Export logs to file\n\n- **GraphQL Mocking** - Full GraphQL endpoint simulation\n  - Import schema from any GraphQL endpoint via introspection\n  - Auto-generate mock operations with placeholder values\n  - Per-operation proxy/mock hybrid mode\n  - Selection set filtering (return only requested fields)\n  - Multi-root-field query support with combined mock/proxy results\n  - Built-in GraphiQL IDE with autocomplete and documentation\n  - See [GraphQL Documentation](docs/graphql.md) for details\n\n- **WebSocket Mocking** - Full WebSocket endpoint simulation\n  - On-connect, on-message (pattern matching), and periodic message handlers\n  - Real-time client management panel (view, send messages, disconnect)\n  - Exact text and regex pattern matching for incoming messages\n  - Configurable delays and intervals\n  - See [WebSocket Documentation](docs/websocket.md) for details\n\n- **Proxy Configuration** - Forward requests to backend services\n  - Prefix or regex-based route matching\n  - Request/response header modification\n  - Automatic decompression of gzipped responses\n\n## Technology Stack\n\n- **Backend:** Express.js, Node.js 20\n- **Database:** SQLite3\n- **Real-time:** Socket.IO\n- **Frontend:** EJS templates, Bootstrap 5, jQuery, DataTables\n- **File Handling:** Multer\n- **Container:** Docker, Docker Compose\n\n## Installation\n\n### Prerequisites\n- Node.js 20+\n- npm or yarn\n\n### Local Development\n\n```bash\n# Clone the repository\ngit clone \u003crepository-url\u003e\ncd mockserver/code\n\n# Install dependencies\nnpm install\n\n# Start in development mode (with auto-reload)\nnpm run start:local\n\n# Start in production mode\nnpm start\n```\n\nThe application will be available at `http://localhost:3880`\n\n## Docker Deployment\n\n### Docker Compose\n\n```bacd code\nversion: '3.4'\n\nservices:\n  mockserver:\n    image: ghcr.io/mateof/mock-server:latest\n    container_name: mockserver\n    restart: unless-stopped\n    environment:\n      - GENERIC_TIMEZONE=Europe/Madrid\n      - TZ=Europe/Madrid\n    #   NODE_ENV: production\n    #   WS_PORT: 3880\n    volumes:\n      - /your/folder/data:/app/data\n    ports:\n      - 3880:3880\n\n```\n\n## Using Docker Compose\n\n```bash\ncd code\n\n# Build and start\ndocker compose up -d --build\n\n# Force rebuild without cache\ndocker compose build --no-cache\ndocker compose up -d\n\n# Or in a single command\ndocker compose up -d --build --force-recreate\n\n# Remove old image and rebuild\ndocker compose down --rmi local\ndocker compose up -d --build\n```\n\n### Using Podman Compose\n\n```bash\n# Force rebuild without cache\npodman compose build --no-cache\npodman compose up -d\n\n# Or in a single command\npodman compose up -d --build --force-recreate\n\n# Remove old image and rebuild\npodman compose down --rmi local\npodman compose up -d --build\n```\n\n## Configuration\n\n### Environment Variables\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `PORT` | 3880 | Server port |\n| `TZ` | Europe/Madrid | Timezone |\n\n### Data Persistence\n\nThe application stores data in the `data/` directory:\n- `database.db` - SQLite database with route configurations\n- `uploads/` - Uploaded files for file-type responses\n\nWhen using Docker, mount a volume to persist data:\n```yaml\nvolumes:\n  - /path/to/your/data:/app/data\n```\n\n## API Reference\n\n### Route Management\n\n| Method | Endpoint | Description |\n|--------|----------|-------------|\n| GET | `/api/routes` | Get all configured routes |\n| POST | `/api/create` | Create a new route |\n| PUT | `/api/update/:id` | Update an existing route |\n| DELETE | `/api/delete/:id` | Delete a route |\n| PUT | `/api/toggle-active/:id` | Enable/disable a route |\n| PUT | `/api/toggle-wait/:id` | Enable/disable wait mode |\n\n### Order Management\n\n| Method | Endpoint | Description |\n|--------|----------|-------------|\n| PUT | `/api/update-order/:id` | Update route priority |\n| PUT | `/api/move-up/:id` | Move route up in priority |\n| PUT | `/api/move-down/:id` | Move route down in priority |\n| PUT | `/api/reorder` | Batch reorder routes |\n| POST | `/api/normalize-order` | Reset order to sequential values |\n\n### GraphQL\n\n| Method | Endpoint | Description |\n|--------|----------|-------------|\n| GET | `/api/graphql-operations/:routeId` | Get GraphQL operations for a route |\n| PUT | `/api/graphql-operations/:routeId` | Save GraphQL operations |\n| POST | `/api/graphql-schema/import` | Import schema from remote endpoint |\n| GET | `/api/graphql-schema/:routeId` | Get stored introspection schema |\n| PUT | `/api/graphql-schema/:routeId` | Save/update introspection schema |\n| GET | `/api/graphql-proxy-url/:routeId` | Get proxy URL for a GraphQL route |\n| PUT | `/api/graphql-proxy-url/:routeId` | Save/update proxy URL |\n\n### WebSocket\n\n| Method | Endpoint | Description |\n|--------|----------|-------------|\n| GET | `/api/ws-messages/:routeId` | Get WebSocket messages for a route |\n| PUT | `/api/ws-messages/:routeId` | Save WebSocket messages |\n| GET | `/api/ws-clients` | Get connected WebSocket clients |\n| POST | `/api/ws-clients/send` | Send message to specific clients |\n| POST | `/api/ws-clients/disconnect` | Disconnect a client |\n\n### Utilities\n\n| Method | Endpoint | Description |\n|--------|----------|-------------|\n| POST | `/api/initTask` | Trigger a waiting request |\n| POST | `/api/validateRegex` | Validate regex patterns |\n\n## Usage Examples\n\n### Creating a Simple JSON Mock\n\n1. Click \"Nueva Ruta\" (New Route)\n2. Select HTTP method (e.g., GET)\n3. Enter route path (e.g., `/api/users`)\n4. Select response type: JSON\n5. Enter response body:\n   ```json\n   {\n     \"users\": [\n       {\"id\": 1, \"name\": \"John\"},\n       {\"id\": 2, \"name\": \"Jane\"}\n     ]\n   }\n   ```\n6. Set status code (e.g., 200)\n7. Save\n\n### Creating a Proxy Route\n\n1. Click \"Nueva Ruta\"\n2. Select HTTP method: ANY\n3. Enter route path (e.g., `/api/external`)\n4. Select response type: Proxy\n5. Enter target URL: `https://api.example.com`\n6. Save\n\n### Using Regex Routes\n\n1. Enable \"Regex\" checkbox\n2. Enter pattern: `/api/users/\\d+`\n3. This will match `/api/users/1`, `/api/users/123`, etc.\n\n### Testing with Wait Mode\n\n1. Enable \"Espera Activa\" (Active Wait) on a route\n2. Send a request to that route\n3. Request will be blocked and appear in pending list\n4. Click \"Pendientes\" to see waiting requests\n5. Click trigger button to release with default or custom response\n\n### Creating a GraphQL Mock\n\n1. Click \"Nueva Ruta\" (New Route)\n2. Select HTTP method: POST\n3. Enter route path: `/graphql`\n4. Select response type: GraphQL\n5. Click **Import Schema** and enter a GraphQL endpoint URL (e.g., `https://rickandmortyapi.com/graphql`)\n6. Operations are auto-generated with mock values — edit responses as needed\n7. Optionally set individual operations to **Proxy** mode to forward to the real API\n8. Save\n9. Click the test button (paper plane icon) to open GraphiQL IDE and test queries\n\nFor a detailed walkthrough, see [GraphQL Documentation](docs/graphql.md).\n\n### Creating a WebSocket Mock\n\n1. Click \"Nueva Ruta\" (New Route)\n2. Enter route path: `/ws/notifications`\n3. Select response type: WebSocket\n4. Add message handlers:\n   - **On Connect**: `{\"type\": \"welcome\", \"message\": \"Connected!\"}`\n   - **On Message** (pattern: `ping`): `pong`\n   - **Periodic** (interval: 5000ms): `{\"type\": \"heartbeat\"}`\n5. Save\n6. Connect from your client:\n   ```javascript\n   const ws = new WebSocket('ws://localhost:3880/ws/notifications');\n   ws.onmessage = (e) =\u003e console.log(e.data);\n   ```\n7. Use **Tools** \u003e **WebSocket Clients** to monitor connections and send manual messages\n\nFor a detailed walkthrough, see [WebSocket Documentation](docs/websocket.md).\n\n### Conditional Responses\n\nConditional responses allow you to return different responses based on request properties (headers, body, query params, etc.). Conditions are evaluated in order - the first matching condition wins.\n\n#### Setting Up Conditional Responses\n\n1. Create or edit a route\n2. Expand the \"Conditional Responses\" section\n3. Click \"Add\" to create a new condition\n4. Enter a criteria expression (JavaScript)\n5. Optionally override: status code, response type, and response body\n6. Drag conditions to reorder priority\n7. Save the route\n\n#### Available Variables\n\n| Variable | Description | Example |\n|----------|-------------|---------|\n| `headers` | Request headers object | `headers['x-api-key']` |\n| `body` | Parsed request body | `body.userId` |\n| `query` | Query parameters | `query.debug` |\n| `path` | URL path | `path` |\n| `params` | Captured regex groups | `params['$1']` |\n| `method` | HTTP method (lowercase) | `method === 'post'` |\n\n#### Available Helper Functions\n\n| Function | Description | Example |\n|----------|-------------|---------|\n| `includes(arr, val)` | Check if array/string contains value | `includes(headers['accept'], 'json')` |\n| `startsWith(str, prefix)` | Check string prefix | `startsWith(path, '/api')` |\n| `endsWith(str, suffix)` | Check string suffix | `endsWith(path, '/list')` |\n| `match(str, regex)` | Test regex pattern | `match(path, '/users/\\\\d+')` |\n| `hasKey(obj, key)` | Check if object has key | `hasKey(body, 'email')` |\n| `isEmpty(val)` | Check if value is empty | `isEmpty(body.name)` |\n| `isNotEmpty(val)` | Check if value is not empty | `isNotEmpty(query.filter)` |\n| `equals(a, b)` | Strict equality | `equals(body.type, 'admin')` |\n| `isNumber(val)` | Check if number | `isNumber(body.age)` |\n| `isString(val)` | Check if string | `isString(body.name)` |\n| `isArray(val)` | Check if array | `isArray(body.items)` |\n| `length(val)` | Get length | `length(body.items) \u003e 0` |\n| `toNumber(val)` | Convert to number | `toNumber(query.page) \u003e 1` |\n| `toLowerCase(val)` | Convert to lowercase | `toLowerCase(headers['x-env']) === 'prod'` |\n\n#### Criteria Expression Examples\n\n```javascript\n// Check header value\nheaders['x-api-key'] === 'premium'\n\n// Check if header exists\nhasKey(headers, 'authorization')\n\n// Check body property\nbody.userId \u003e 1000\n\n// Check query parameter\nquery.debug === 'true'\n\n// Check HTTP method\nmethod === 'post'\n\n// Combined conditions with AND\nheaders['x-api-key'] \u0026\u0026 body.type === 'admin'\n\n// Combined conditions with OR\nbody.env === 'test' || query.mock === 'true'\n\n// Using helper functions\nhasKey(body, 'email') \u0026\u0026 isNotEmpty(body.email)\n\n// Regex match on path\nmatch(path, '/users/\\\\d+')\n\n// Check if header contains value\nincludes(headers['content-type'], 'json')\n\n// Check array length\nisArray(body.items) \u0026\u0026 length(body.items) \u003e 0\n\n// Check numeric comparison\ntoNumber(body.amount) \u003e= 100\n\n// Complex condition\nheaders['x-env'] === 'staging' \u0026\u0026 hasKey(body, 'testMode') \u0026\u0026 body.testMode === true\n```\n\n#### Use Case Example\n\nFor an endpoint `/api/users`, you might want:\n\n1. **Condition 1** - Premium users: `headers['x-subscription'] === 'premium'`\n   - Return: Full user data with extra fields\n\n2. **Condition 2** - Error simulation: `query.simulate === 'error'`\n   - Return: 500 status with error message\n\n3. **Condition 3** - Empty results: `query.filter === 'none'`\n   - Return: Empty array `[]`\n\n4. **Default** - Standard response for all other requests\n\n## License\n\nThis project is licensed under the GNU General Public License v3.0 - see the [LICENSE](LICENSE) file for details.\n\n## Contributing\n\nThis is a private project. Please contact the maintainers for contribution guidelines.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmateof%2Fmock-server","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmateof%2Fmock-server","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmateof%2Fmock-server/lists"}