12 KiB
Configurable Mock API with Admin Interface
A lightweight, configurable mock API application in Python that allows dynamic endpoint management via an admin interface. The API serves customizable responses stored in a SQLite database with template variable support.
Features
- Dynamic Endpoint Configuration: Create, read, update, and delete API endpoints through a web-based admin interface.
- Template Variable Support: Response bodies can include Jinja2 template variables (e.g.,
{{ user_id }},{{ timestamp }}) populated from path parameters, query strings, headers, request body, system variables, and endpoint defaults. - Dynamic Route Registration: Endpoints are registered/unregistered at runtime without restarting the server.
- Admin Interface: Secure web UI with session-based authentication for managing endpoints.
- Production Ready: Uses Waitress WSGI server, SQLAlchemy async, and FastAPI with proper error handling and security measures.
Technology Stack
- Framework: FastAPI (with automatic OpenAPI documentation)
- Server: Waitress (production WSGI server)
- Database: SQLite with SQLAlchemy 2.0 async ORM
- Templating: Jinja2 with sandboxed environment
- Authentication: Session-based with bcrypt password hashing
- Frontend: Bootstrap 5 (CDN) for admin UI
Project Structure
mockapi/
├── app.py # FastAPI application factory & lifespan
├── config.py # Configuration (Pydantic Settings)
├── database.py # SQLAlchemy async database setup
├── dependencies.py # FastAPI dependencies
├── example_usage.py # Integration test & demonstration script
├── middleware/
│ └── auth_middleware.py # Admin authentication middleware
├── models/
│ └── endpoint_model.py # Endpoint SQLAlchemy model
├── observers/
│ └── __init__.py # Observer pattern placeholder
├── repositories/
│ └── endpoint_repository.py # Repository pattern for endpoints
├── run.py # Development runner script (with auto-reload)
├── services/
│ ├── route_service.py # Dynamic route registration/management
│ └── template_service.py # Jinja2 template rendering
├── controllers/
│ └── admin_controller.py # Admin UI routes
├── schemas/
│ └── endpoint_schema.py # Pydantic schemas for validation
├── templates/ # Jinja2 HTML templates
│ ├── base.html # Base layout
│ └── admin/
│ ├── login.html # Login page
│ ├── dashboard.html # Admin dashboard
│ ├── endpoints.html # Endpoint list
│ └── endpoint_form.html # Create/edit endpoint
├── static/
│ └── css/ # Static CSS (optional)
├── tests/ # Test suite
│ ├── test_admin.py # Admin authentication tests
│ ├── test_endpoint_repository.py
│ └── test_route_manager_fix.py
├── utils/ # Utility modules
│ └── __init__.py
├── requirements.txt # Python dependencies
├── .env.example # Example environment variables
├── .env # Local environment variables (create from .env.example)
├── run_example.sh # Script to run the integration test
└── README.md # This file
Installation
-
Navigate to project directory:
cd ~/GitLab/customer-engineering/mockapi -
Create a virtual environment (recommended):
python3 -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate -
Install dependencies:
pip install -r requirements.txt -
Configure environment variables:
cp .env.example .env # Edit .env with your settingsExample
.env:DATABASE_URL=sqlite+aiosqlite:///./mockapi.db ADMIN_USERNAME=admin ADMIN_PASSWORD=admin123 # Change this in production! SECRET_KEY=your-secret-key-here # Change this! DEBUG=True # Set to False in production -
Initialize the database (tables are created automatically on first run).
Running the Application
Development (with auto‑reload)
Make sure your virtual environment is activated:
source venv/bin/activate # Linux/macOS
# venv\Scripts\activate # Windows
Then run with auto-reload for development:
# Using run.py (convenience script)
python run.py
# Or directly with uvicorn
uvicorn app:app --reload --host 0.0.0.0 --port 8000
Production (with Waitress)
For production deployment, use Waitress WSGI server with the provided WSGI adapter (a2wsgi):
waitress-serve --host=0.0.0.0 --port=8000 --threads=4 wsgi:wsgi_app
The server will start on http://localhost:8000 (or your configured host/port).
Note: Waitress is a WSGI server, but FastAPI is an ASGI framework. The wsgi.py file uses a2wsgi to wrap the ASGI application into a WSGI-compatible interface. Routes are automatically refreshed from the database on server startup.
Production Deployment Considerations
1. Environment Configuration
- Set
DEBUG=Falsein production - Use strong, unique values for
ADMIN_PASSWORDandSECRET_KEY - Consider using a more robust database (PostgreSQL) by changing
DATABASE_URL - Store sensitive values in environment variables or a secrets manager
2. Process Management
Use a process manager like systemd (Linux) or Supervisor to keep the application running:
Example systemd service (/etc/systemd/system/mockapi.service):
[Unit]
Description=Mock API Service
After=network.target
[Service]
User=www-data
Group=www-data
WorkingDirectory=/path/to/mockapi
Environment="PATH=/path/to/mockapi/venv/bin"
ExecStart=/path/to/mockapi/venv/bin/waitress-serve --host=0.0.0.0 --port=8000 wsgi:wsgi_app
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
3. Reverse Proxy (Recommended)
Use Nginx or Apache as a reverse proxy for SSL termination, load balancing, and static file serving:
Example Nginx configuration:
server {
listen 80;
server_name api.yourdomain.com;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
4. Database Backups
For SQLite, regularly backup the mockapi.db file. For production, consider migrating to PostgreSQL.
Usage
1. Access the Admin Interface
- Open
http://localhost:8000/admin/login - Log in with the credentials set in
.env(default:admin/admin123)
2. Create a Mock Endpoint
- Navigate to Endpoints → Create New.
- Fill in the form:
- Route:
/api/greeting/{name}(supports path parameters) - Method: GET
- Response Body:
{ "message": "Hello, {{ name }}!" } - Response Code: 200
- Content-Type:
application/json - Variables:
{ "server": "mock-api" }(optional defaults)
- Route:
- Click Create.
3. Call the Mock Endpoint
curl http://localhost:8000/api/greeting/World
Response:
{ "message": "Hello, World!" }
4. Template Variables
The following variable sources are available in response templates:
| Source | Example variable | Usage in template |
|---|---|---|
| Path parameters | {{ name }} |
/users/{id} → {{ id }} |
| Query parameters | {{ query.page }} |
?page=1 → {{ page }} |
| Request headers | {{ header.authorization }} |
Authorization: Bearer token |
| Request body | {{ body.user.email }} |
JSON request body |
| System variables | {{ timestamp }}, {{ request_id }} |
Automatically injected |
| Endpoint defaults | {{ server }} |
Defined in endpoint variables |
5. Admin Functions
- List endpoints with pagination and filtering
- Edit existing endpoints (changes take effect immediately)
- Activate/deactivate endpoints without deletion
- Delete endpoints (removes route)
- Dashboard with statistics (total endpoints, active routes, etc.)
Security Considerations
- Admin authentication: Uses bcrypt password hashing. Store a strong password hash in production.
- Session management: Signed cookies with configurable secret key.
- Template sandboxing: Jinja2 environment restricted with
SandboxedEnvironmentandStrictUndefined. - Request size limits: Maximum body size of 1MB to prevent DoS.
- Route validation: Prevents path traversal (
..) and other unsafe patterns. - SQL injection protection: All queries use SQLAlchemy ORM.
Configuration Options
See config.py for all available settings. Key environment variables:
| Variable | Default | Description |
|---|---|---|
DATABASE_URL |
sqlite+aiosqlite:///./mockapi.db |
SQLAlchemy database URL |
ADMIN_USERNAME |
admin |
Admin login username |
ADMIN_PASSWORD |
admin123 |
Admin login password (plaintext) |
SECRET_KEY |
your‑secret‑key‑here‑change‑me |
Session signing secret |
DEBUG |
False |
Enable debug mode (more logging, relaxed validation) |
Warning: In production (DEBUG=False), the default ADMIN_PASSWORD and SECRET_KEY will cause validation errors. You must set unique values via environment variables.
API Documentation
FastAPI automatically provides OpenAPI documentation at:
- Swagger UI:
http://localhost:8000/docs - ReDoc:
http://localhost:8000/redoc
The root URL (/) automatically redirects to the Swagger documentation at /docs.
The dynamic mock endpoints are not listed in the OpenAPI schema (they are registered at runtime).
Development & Testing
Running Tests
Run tests with pytest:
pytest tests/
The test suite includes:
- Unit tests for repository and service layers
- Integration tests for admin authentication
- Template rendering tests
Example Integration Test
A ready‑to‑run integration test demonstrates the core functionality:
# Make the script executable (Linux/macOS)
chmod +x run_example.sh
# Run the example
./run_example.sh
Or directly with Python:
python example_usage.py
The example script will:
- Start the FastAPI app (via TestClient)
- Log in as admin
- Create a mock endpoint with template variables
- Call the endpoint and verify the response
- Report success or failure
This is a great way to verify that the API is working correctly after installation.
Troubleshooting
Common Issues
-
"no such table: endpoints" error
- The database hasn't been initialized
- Restart the application - tables are created on first startup
- Or run
python -c "from database import init_db; import asyncio; asyncio.run(init_db())"
-
Login fails even with correct credentials
- Check that
DEBUG=Trueis set in.env(or provide unique credentials) - The default credentials only work when
DEBUG=True - In production, you must set unique
ADMIN_PASSWORDandSECRET_KEY
- Check that
-
Routes not being registered
- Check that the endpoint is marked as active (
is_active=True) - Refresh the page - routes are registered immediately after creation
- Check application logs for errors
- Check that the endpoint is marked as active (
-
Template variables not rendering
- Ensure you're using double curly braces:
{{ variable }} - Check variable names match the context (use path_, query_, header_ prefixes as needed)
- View the rendered template in the admin edit form preview
- Ensure you're using double curly braces:
Logging
Enable debug logging by setting DEBUG=True in .env. Check the console output for detailed error messages.
Limitations & Future Enhancements
-
Current limitations:
- SQLite only (but can be extended to PostgreSQL via
DATABASE_URL) - Single admin user (no multi‑user support)
- No request logging/history
- SQLite only (but can be extended to PostgreSQL via
-
Possible extensions:
- Import/export endpoints as JSON/YAML
- Request logging and analytics
- WebSocket notifications for admin actions
- Multiple admin users with roles
- Rate limiting per endpoint
- CORS configuration
License
This project is provided as-is for demonstration purposes. Use at your own risk.
Acknowledgments
- Built with FastAPI, SQLAlchemy, and Jinja2.
- Admin UI uses Bootstrap 5 via CDN.