mockapi/README.md
2026-03-16 05:47:01 +00:00

356 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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
1. **Navigate to project directory**:
```bash
cd ~/GitLab/customer-engineering/mockapi
```
2. **Create a virtual environment** (recommended):
```bash
python3 -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
```
3. **Install dependencies**:
```bash
pip install -r requirements.txt
```
4. **Configure environment variables**:
```bash
cp .env.example .env
# Edit .env with your settings
```
Example `.env`:
```ini
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
```
5. **Initialize the database** (tables are created automatically on first run).
## Running the Application
### Development (with autoreload)
Make sure your virtual environment is activated:
```bash
source venv/bin/activate # Linux/macOS
# venv\Scripts\activate # Windows
```
Then run with auto-reload for development:
```bash
# 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):
```bash
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=False` in production
- Use strong, unique values for `ADMIN_PASSWORD` and `SECRET_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`)**:
```ini
[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**:
```nginx
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
1. Navigate to **Endpoints****Create New**.
2. 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)
3. Click **Create**.
### 3. Call the Mock Endpoint
```bash
curl http://localhost:8000/api/greeting/World
```
Response:
```json
{ "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 `SandboxedEnvironment` and `StrictUndefined`.
- **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` | `yoursecretkeyherechangeme` | 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:
```bash
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 readytorun integration test demonstrates the core functionality:
```bash
# Make the script executable (Linux/macOS)
chmod +x run_example.sh
# Run the example
./run_example.sh
```
Or directly with Python:
```bash
python example_usage.py
```
The example script will:
1. Start the FastAPI app (via TestClient)
2. Log in as admin
3. Create a mock endpoint with template variables
4. Call the endpoint and verify the response
5. Report success or failure
This is a great way to verify that the API is working correctly after installation.
## Troubleshooting
### Common Issues
1. **"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())"`
2. **Login fails even with correct credentials**
- Check that `DEBUG=True` is set in `.env` (or provide unique credentials)
- The default credentials only work when `DEBUG=True`
- In production, you must set unique `ADMIN_PASSWORD` and `SECRET_KEY`
3. **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
4. **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
### 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 multiuser support)
- No request logging/history
- **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](https://fastapi.tiangolo.com/), [SQLAlchemy](https://www.sqlalchemy.org/), and [Jinja2](https://jinja.palletsprojects.com/).
- Admin UI uses [Bootstrap 5](https://getbootstrap.com/) via CDN.