A simple, file-based API mocking server.
Project description
Simple API Mock Server
A simple, file-based API mocking server built with Flask, designed to help developers quickly simulate API endpoints for testing and development.
🔧 Features
Core Functionality
- Dynamic Routing: Define API endpoints from a
api.jsonorapi.yamlfile. - OpenAPI Specification: Automatically generates a rich OpenAPI v3 specification at
/openapi.json. - Metrics Endpoint: Exposes Prometheus-style metrics at
/metrics. - Graceful 404 Handling: Custom JSON 404 responses for unknown routes.
- CORS Support: Integrated
Flask-Corsto handle Cross-Origin Resource Sharing.
Configuration & Customization
- YAML Configuration: Supports
.ymland.yamlconfiguration files. - Templating for Request Body Parameters: Responses can be dynamically templated using values from the request body.
- Custom Response Headers per Method: Define specific HTTP headers for different methods within the same route.
- Descriptions and Metadata: Add optional
descriptionandtagsfields to your API endpoints for better documentation and categorization. - Example Request Bodies: Include optional
request_bodyfields inapi.jsonfor documenting expected request payloads. - Static File Serving: Serve static files (e.g., UI assets) from a specified folder via a CLI argument.
Authentication & Security
- Improved Authentication Logic: Refactored for clarity, consistency, and maintainability.
- Granular Rate Limiting: Rate limiting can now be applied per client IP or API key for more realistic throttling. Old rate limit entries are pruned to prevent memory growth.
- API Key in Query Params: API keys can be sent via query parameters (
?api_key=...) as well as headers. - Auth Challenge Headers: 401 Unauthorized responses for Basic and Bearer auth now include
WWW-Authenticateheaders.
Development & Operations
- Enhanced Metrics Tracking: Thread-safe and semantically clearer metrics using
collections.Counter. - Robust Error Handling: Improved error logging with
logger.exception()and user-friendly messages for port binding errors and malformed JSON. - Thread-Safe Rate Limiting: Implemented
threading.Lockto prevent race conditions in rate limiting. - Hot Reloading: Automatically restarts the server when
api.jsonchanges (requires--debugflag). - Graceful Shutdown: Handles
SIGINT,SIGTERM, andKeyboardInterruptfor clean server termination. - Comprehensive Logging: Detailed logging for server operations, requests, and errors.
- Modular Configuration: Separated configuration validation and loading logic into a dedicated module.
Installation
From PyPI (Recommended, once published)
pip install simple-api-mock-server
From Source
-
Clone the repository:
</code></pre> </li> </ol> <p>git clone <a href="https://github.com/sanatladkat/simple-api-mock-server.git">https://github.com/sanatladkat/simple-api-mock-server.git</a> cd simple-api-mock-server ```</p> <ol start="2"> <li> <p><strong>Create a virtual environment:</strong></p> <pre><code class="language-bash">
python -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate ```
-
Install dependencies:
</code></pre> </li> </ol> <p>pip install -r requirements.txt pip install -e . ```</p> <h2><a href="#user-content--quick-start" aria-hidden="true" class="anchor" id="user-content--quick-start"></a>🚀 Quick Start</h2> <p>To get a mock server up and running quickly:</p> <ol> <li> <p><strong>Create a file <code>api.json</code> or <code>api.yaml</code></strong> with the following content:</p> <pre><code class="language-yaml">
- path: /hello
methods:
- GET response: data: message: "Hello, world!" code: 200
-
Run the server from your project root:
</code></pre> </li> </ol> <p>simple-mock-server --config api.yaml ```</p> <ol start="3"> <li><strong>Visit:</strong> <code>http://localhost:5001/hello</code> in your browser or API client.</li> </ol> <h2><a href="#user-content--pypi-package" aria-hidden="true" class="anchor" id="user-content--pypi-package"></a>📦 PyPI Package</h2> <p>You can install via pip:</p> <pre><code class="language-bash">pip install simple-api-mock-server
📄 View on PyPI # Placeholder: Update with actual PyPI link after publishing
Usage
-
Create an
api.jsonorapi.yamlfile:This file defines your API endpoints and their responses. See the Configuration section for details and examples.
-
Run the server:
</code></pre> </li> </ol> <p>simple-mock-server --config api.json --port 5001 --debug --verbose --static-folder ./static ```</p> <pre><code>**CLI Options:** * `--config <path>`: Path to the API configuration file (JSON or YAML). (default: `api.json`). * `--port <number>`: Port to run the server on (default: `5001`). * `--host <address>`: Host to bind the server to (default: `127.0.0.1`). * `--debug`: Enable Flask debug mode and hot reloading (auto-reloader for code changes). * `--verbose`: Enable verbose logging. * `--static-folder <path>`: Path to a static folder to serve files from (e.g., for UI assets). Static files will be served at `/static/<filename>`.
-
Access the mock API:
The server will be running at
http://127.0.0.1:5001(or your specified port).
⚠️ Security Note
This mock server is intended for development and testing purposes only. It should not be exposed to the public internet or used in production environments, as it lacks proper authentication, authorization, and input validation safeguards beyond simulation.
🛠️ Configuration Reference
The configuration file (JSON or YAML) is a list of route objects. Each route object can have the following properties:
path(string, required): The URL path for the endpoint (e.g.,/users,/users/{user_id}). Flask's route variable syntax is supported.methods(array of strings, required): A list of HTTP methods this endpoint responds to (e.g.,["GET", "POST"]).response(object, required): An object defining the response to return.data(object or array, required): The JSON content to return as the response body.- Dynamic Responses:
- Route Variables: Use
{variable_name}in the response JSON to inject values from route variables (e.g.,"id": "{user_id}"). - Query Parameters: Use
{query_param:param_name}to inject values from URL query parameters (e.g.,"message": "Hello, {query_param:name}!"). - Request Body Parameters: Use
{body_param:param_name}to inject values from the JSON request body (e.g.,"received_name": "{body_param:name}").
- Route Variables: Use
- Echo Request Body: Include
"echo": truein thedataobject to have the server return the same JSON request body it received (instead of the static data response). Useful for testing POST/PUT payloads.
- Dynamic Responses:
code(integer, optional): The HTTP status code to return (default:200). For204 No Contentresponses, the body will be empty.delay(number, optional): The delay in seconds before sending the response, simulating network latency (default:0).headers(object, optional): A dictionary of custom HTTP headers to include in the response (e.g.,"X-Custom-Header": "MyValue"). Headers can also be templated.
description(string, optional): A brief description of the endpoint's purpose.tags(array of strings, optional): A list of tags for categorizing the endpoint.auth(object, optional): Configuration for authentication simulation.api_key(string, required ifauthis present): The expected API key. The server will look for this in theX-API-Keyheader orapi_keyquery parameter. If it doesn't match, a401 Unauthorizedresponse is returned.basic_auth(object, optional): Basic authentication credentials (username,password). If authentication fails, a401 Unauthorizedresponse with aWWW-Authenticate: Basic realm="Authentication Required"header is returned.bearer_token(string, optional): Bearer token. If authentication fails, a401 Unauthorizedresponse with aWWW-Authenticate: Bearer realm="Authentication Required"header is returned.skip_auth(boolean, optional): Set totrueto disable authentication for this endpoint.
rate_limit(object, optional): Configuration for rate limiting.requests(integer, required): Maximum number of requests allowed.window(integer, required): Time window in seconds for the rate limit.- Rate limit headers (
X-RateLimit-Limit,X-RateLimit-Remaining,Retry-After) are automatically included in responses. Rate limiting is applied per client IP or API key.
request_body(object, optional): An example or schema for the expected request body (for documentation/validation).query_params(array of objects, optional): A list of query parameters for the endpoint.name(string, required): The name of the query parameter.required(boolean, optional): Whether the query parameter is required (default:false).type(string, optional): The type of the query parameter (default:string).
api.yamlExample- path: / methods: - GET description: Welcome endpoint tags: - General response: data: message: Welcome to the mock server! code: 200 - path: /api/users methods: - GET description: Get all users tags: - Users response: data: - id: 1 name: John Doe - id: 2 name: Jane Doe code: 200 - path: /api/users methods: - POST description: Create a new user tags: - Users request_body: name: string email: string response: data: message: User {body_param:name} created successfully code: 201 - path: /api/users/{user_id} methods: - GET description: Get user by ID tags: - Users response: data: id: "{user_id}" name: "User {user_id}" headers: X-User-Id: "{user_id}" code: 200 - path: /api/greet methods: - GET description: Greet a user by name from query param tags: - Utilities query_params: - name: name required: true type: string response: data: message: "Hello, {query_param:name}!" code: 200 - path: /api/protected methods: - GET description: Protected endpoint with API key authentication tags: - Authentication response: data: message: Access granted! code: 200 auth: api_key: my-secret-api-key - path: /api/rate-limited methods: - GET description: Endpoint with rate limiting enabled (2 requests per 60 seconds) tags: - Rate Limiting response: data: message: You are not rate limited yet! code: 200 rate_limit: requests: 2 window: 60
For a more comprehensive example, refer to the
api.jsonexample below.Testing
To run the unit and integration tests, navigate to the project root and execute:
pip install ".[dev]" # Install development dependencies (requests, pytest) for running tests and contributing to development. pytest
❗ Troubleshooting
Versioning and Changelog
See the CHANGELOG.md for details on releases and changes.
License
This project is licensed under the MIT License - see the LICENSE file for details.
-
-
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file simple-api-mock-server-0.3.1.tar.gz.
File metadata
- Download URL: simple-api-mock-server-0.3.1.tar.gz
- Upload date:
- Size: 16.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.7.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1abd2b549581a0b77a6bea6a0dd8a0cc6fbe1566e00564d82b04375d760d9d41
|
|
| MD5 |
f8a9cc028b78ecfd077f633ebdb2f60e
|
|
| BLAKE2b-256 |
74ad420f21e97a6b7b015546c8ba492c903f5340c471fbf7d6d29fad8462fcff
|
File details
Details for the file simple_api_mock_server-0.3.1-py3-none-any.whl.
File metadata
- Download URL: simple_api_mock_server-0.3.1-py3-none-any.whl
- Upload date:
- Size: 17.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.7.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7fe8c81eeff04b70b4e2e5091d86242f0caba62c5aedbcc15d653d2b5aa1e88a
|
|
| MD5 |
470d16e50f83cf5ca6dc2df9a6b4441e
|
|
| BLAKE2b-256 |
425fa205a8b4f06234e4caaa1e1f5459961a8b5cda20555f9985f68ff1c39f6d
|