api-simulator


Nameapi-simulator JSON
Version 0.3.0 PyPI version JSON
download
home_pageNone
SummaryMulti-protocol API mocking made simple - REST, GraphQL, WebSocket, UDP from a single JSON config
upload_time2025-08-16 01:24:37
maintainerNone
docs_urlNone
authorNone
requires_python>=3.9
licenseMIT
keywords api mock simulator rest graphql websocket udp testing development
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # API Simulator

<div align="center">

[![Python](https://img.shields.io/badge/python-3.9%2B-blue)](https://www.python.org)
[![License](https://img.shields.io/badge/license-MIT-green)](LICENSE)
[![Version](https://img.shields.io/badge/version-0.3.0-orange)](https://github.com/yourusername/api-simulator)

**Multi-protocol API mocking made simple** • REST • GraphQL • WebSocket • UDP

[Features](#features) • [Quick Start](#quick-start) • [Documentation](#documentation) • [Examples](#examples) • [Contributing](#contributing)

</div>

---

## 🎯 Overview

API Simulator spins up lifelike backends from a single JSON configuration file. Perfect for frontend development, integration testing, and API prototyping without waiting for backend implementation.

### Key Features

- 🚀 **Zero dependencies** - Just Python and a JSON config
- 🔌 **Multi-protocol** - REST, GraphQL, WebSocket, and UDP from one server
- 📝 **Request-aware templating** - Dynamic responses based on headers, query params, and paths
- 🎭 **Realistic behavior** - Rules, delays, errors, and chaos testing
- 📊 **Streaming support** - SSE, NDJSON, and WebSocket broadcasts
- 🔒 **HTTPS/WSS ready** - Built-in TLS support
- 📖 **OpenAPI export** - Auto-generated documentation

## 🚀 Quick Start

### Installation

```bash
pip install -e .
```

### Basic Usage

1. **Create a config file** (`config.json`):

```json
{
  "rest": {
    "port": 3000,
    "path": "/api",
    "apis": [
      {
        "method": "GET",
        "path": "/users/{user_id}",
        "response": {
          "id": "{{ path('user_id') }}",
          "name": "Test User",
          "created": "{{ timestamp() }}"
        }
      }
    ]
  }
}
```

2. **Start the simulator**:

```bash
apisim run --config config.json
```

3. **Test your API**:

```bash
curl http://localhost:3000/api/users/123
```

## 📚 Documentation

### Table of Contents

- [CLI Commands](#cli-commands)
- [Configuration](#configuration)
- [Templating](#templating)
- [Protocols](#protocols)
  - [REST API](#rest-api)
  - [WebSocket](#websocket)
  - [GraphQL](#graphql)
  - [UDP Streaming](#udp-streaming)
- [Advanced Features](#advanced-features)

## 🛠️ CLI Commands

### Server Management

```bash
# Start server
apisim run --config config.json [options]
  --templates templates.json  # Template macros
  --seed 42                   # Deterministic randomness
  --log-level INFO           # Logging level
  --certfile cert.pem        # HTTPS/WSS certificate
  --keyfile key.pem          # HTTPS/WSS key

# Check running servers
apisim status

# Stop servers
apisim stop [--all]

# Validate configuration
apisim validate --config config.json

# Export OpenAPI spec
apisim openapi export --config config.json [--out openapi.json]
```

## ⚙️ Configuration

### REST API

```json
{
  "rest": {
    "port": 3000,
    "path": "/api/v1",
    "apis": [
      {
        "method": "GET",
        "path": "/products/{product_id}",
        "response": {...},      // JSON response
        "text": "plain text",   // Text response
        "file": "path/to/file", // File response
        "binary_b64": "...",    // Binary response
        "stream": {...},        // NDJSON streaming
        "sse": {...},          // Server-Sent Events
        "rules": {...}         // Conditional behavior
      }
    ]
  }
}
```

#### Streaming Responses

**Server-Sent Events (SSE)**:
```json
{
  "method": "GET",
  "path": "/events",
  "sse": {
    "interval": 1,
    "event": "update",
    "template": {"price": "{{ random_float(100,200,2) }}"},
    "count": 10  // null for infinite
  }
}
```

**NDJSON Streaming**:
```json
{
  "method": "GET",
  "path": "/stream",
  "stream": {
    "interval": 0.5,
    "template": {"seq": "{{ counter('seq') }}"},
    "content_type": "application/x-ndjson"
  }
}
```

### WebSocket

```json
{
  "websocket": {
    "port": 9080,
    "path": "/ws",
    "apis": [
      {
        "path": "/events",
        "response": {"type": "ack"},
        "broadcast": {
          "interval": 5,
          "response": {"event": "{{ counter('events') }}"}
        },
        "rules": {
          "message.action == 'subscribe'": {
            "response": {"subscribed": true}
          }
        }
      }
    ]
  }
}
```

### GraphQL

```json
{
  "graphql": {
    "port": 3000,
    "path": "/graphql",
    "queries": [
      {
        "operationName": "GetUser",
        "response": {"user": {"id": "123", "name": "Alice"}}
      }
    ],
    "mutations": [
      {
        "operationName": "CreateUser",
        "response": {"success": true, "id": "{{ uuid4() }}"}
      }
    ],
    "subscriptions": [
      {
        "operationName": "UserUpdates",
        "interval": 2,
        "response": {"user": {"updated": "{{ timestamp() }}"}}
      }
    ]
  }
}
```

### UDP Broadcasting

```json
{
  "udp": {
    "host": "127.0.0.1",
    "port": 5001,
    "apis": [
      {
        "name": "telemetry",
        "broadcast": {
          "interval": 1,
          "response": {"temp": "{{ random_float(20,30,1) }}"}
        }
      }
    ]
  }
}
```

## 🎨 Templating

### Built-in Functions

| Function | Description | Example |
|----------|-------------|---------|
| `{{ timestamp() }}` | ISO 8601 timestamp | `2024-01-15T10:30:00Z` |
| `{{ unix_timestamp() }}` | Unix timestamp | `1705315800` |
| `{{ uuid4() }}` | UUID v4 | `a3bb189e-8bf9-4c90-b8f0-d7d3e7e4d6c1` |
| `{{ random_int(min, max) }}` | Random integer | `{{ random_int(1, 100) }}` |
| `{{ random_float(min, max, decimals) }}` | Random float | `{{ random_float(0, 1, 2) }}` |
| `{{ counter(name, start, step) }}` | Auto-incrementing counter | `{{ counter('order', 1000, 1) }}` |
| `{{ choice([...]) }}` | Random selection | `{{ choice(['A', 'B', 'C']) }}` |

### Request-Aware Templates

Access request data in responses:

```json
{
  "response": {
    "path_param": "{{ path('user_id') }}",
    "query_param": "{{ query('search') }}",
    "header": "{{ header('Authorization') }}",
    "body_field": "{{ body('email') }}",
    "method": "{{ method() }}"
  }
}
```

### Custom Macros

Define reusable templates in `templates.json`:

```json
{
  "functions": {
    "order_id": "counter('order', 1000, 1)",
    "product": "choice(['Widget', 'Gadget', 'Tool'])",
    "price": "random_float(10.0, 100.0, 2)"
  }
}
```

## 🎯 Rules & Conditional Behavior

### Rule Conditions

- **Probability**: `"0.1"` (10% chance)
- **Path equality**: `"path.user_id == '123'"`
- **Query params**: `"query.debug == 'true'"`
- **Headers**: `"header.X-Test == 'yes'"`
- **Body fields**: `"body.amount > 100"`

### Actions

```json
{
  "rules": {
    "query.test == 'error'": {
      "status": 500,
      "response": {"error": "Test error"},
      "headers": {"X-Error": "true"}
    },
    "header.X-Slow == 'true'": {
      "delay": "2s"
    },
    "0.05": {
      "ignore": true  // 5% drop rate
    }
  }
}
```

## 🧪 Testing

### Running Tests

```bash
# All tests
pytest tests/ -v

# Specific protocols
pytest tests/test_protocols.py::TestRESTProtocol -v
pytest tests/test_e2e_protocols.py -v

# With coverage
pytest tests/ --cov=api_simulator
```

### Test Structure

```
tests/
├── test_cli.py           # CLI command tests
├── test_protocols.py     # Protocol unit tests
└── test_e2e_protocols.py # End-to-end with lifespan
```

## 📖 Examples

### Complete E-Commerce API

See [`examples/config.json`](examples/config.json) for a full example with:
- Product catalog with search
- Order streaming
- Real-time price updates (SSE)
- WebSocket order events
- GraphQL customer queries
- UDP inventory feeds

### Testing Different Protocols

After starting the server with `apisim run --config examples/config.json`:

**REST API Tests:**
```bash
# Basic GET endpoint
curl http://localhost:3000/api/v1/status

# Path parameters, query strings, and headers
curl "http://localhost:3000/api/v1/products/PROD-123?q=search" \
  -H "X-Session-Id: test-session"

# SSE streaming (real-time price updates)
curl -N http://localhost:3000/api/v1/prices/sse

# NDJSON streaming 
curl -N http://localhost:3000/api/v1/stream/orders
```

**GraphQL Tests:**
```bash
# Query
curl -X POST http://localhost:3000/graphql \
  -H "Content-Type: application/json" \
  -d '{"operationName":"GetCustomer"}'

# Mutation
curl -X POST http://localhost:3000/graphql \
  -H "Content-Type: application/json" \
  -d '{"operationName":"CreateOrder"}'

# List available operations
curl http://localhost:3000/openapi.json | jq '.paths."/graphql"'
```

**WebSocket Tests:**
```bash
# Using wscat (npm install -g wscat)
wscat -c ws://localhost:9080/realtime/events
> {"action":"subscribe"}

# Using Python
python3 -c "
import asyncio, websockets, json
async def test():
    async with websockets.connect('ws://localhost:9080/realtime/events') as ws:
        await ws.send(json.dumps({'action': 'subscribe'}))
        print(await ws.recv())
asyncio.run(test())
"

# GraphQL Subscriptions
python3 -c "
import asyncio, websockets, json
async def test():
    async with websockets.connect('ws://localhost:9080/realtime/graphql') as ws:
        await ws.send(json.dumps({'type': 'connection_init'}))
        print(await ws.recv())
        await ws.send(json.dumps({'id': '1', 'type': 'subscribe', 
                                 'payload': {'operationName': 'PriceUpdates'}}))
        print(await ws.recv())
asyncio.run(test())
"
```

**UDP Listener:**
```bash
python3 -c "
import socket, struct, msgpack
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(('127.0.0.1', 5001))
print('Listening on 127.0.0.1:5001...')
while True:
    pkt, _ = s.recvfrom(65536)
    magic, ts, n = struct.unpack('>IIH', pkt[:10])
    print(f'Magic: 0x{magic:X}, Payload:', msgpack.unpackb(pkt[10:], raw=False))
"
```

## 🔌 API Documentation

When running, access auto-generated API docs at:

- **Swagger UI**: http://localhost:3000/docs
- **ReDoc**: http://localhost:3000/redoc
- **OpenAPI JSON**: http://localhost:3000/openapi.json

## 🐳 Docker

```dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY . .
RUN pip install -e .
CMD ["apisim", "run", "--config", "/config/config.json"]
```

```bash
docker build -t api-simulator .
docker run -p 3000:3000 -p 9080:9080 \
  -v $(pwd)/examples:/config \
  api-simulator
```

## 🤝 Contributing

We welcome contributions! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.

### Development Setup

```bash
# Clone repository
git clone https://github.com/yourusername/api-simulator
cd api-simulator

# Create virtual environment
python -m venv venv
source venv/bin/activate  # or `venv\Scripts\activate` on Windows

# Install with dev dependencies
pip install -e ".[test]"

# Run tests
pytest tests/ -v

# Check code style
ruff check src/
```

## 📝 License

MIT License - see [LICENSE](LICENSE) file for details.

## 🙏 Acknowledgments

Built with:
- [FastAPI](https://fastapi.tiangolo.com/) - REST/GraphQL server
- [websockets](https://websockets.readthedocs.io/) - WebSocket support
- [msgpack](https://msgpack.org/) - Binary serialization
- [Pydantic](https://pydantic-docs.helpmanual.io/) - Data validation

## 📮 Support

- 📧 Email: support@example.com
- 💬 Discord: [Join our server](https://discord.gg/example)
- 🐛 Issues: [GitHub Issues](https://github.com/yourusername/api-simulator/issues)

---

<div align="center">
Made with ❤️ by the API Simulator Team
</div>

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "api-simulator",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.9",
    "maintainer_email": null,
    "keywords": "api, mock, simulator, rest, graphql, websocket, udp, testing, development",
    "author": null,
    "author_email": "API Simulator Team <support@example.com>",
    "download_url": "https://files.pythonhosted.org/packages/c1/bd/abbce2400e5d2e0f68d977075ac41c559c709b4994028a2994619147c2bb/api_simulator-0.3.0.tar.gz",
    "platform": null,
    "description": "# API Simulator\n\n<div align=\"center\">\n\n[![Python](https://img.shields.io/badge/python-3.9%2B-blue)](https://www.python.org)\n[![License](https://img.shields.io/badge/license-MIT-green)](LICENSE)\n[![Version](https://img.shields.io/badge/version-0.3.0-orange)](https://github.com/yourusername/api-simulator)\n\n**Multi-protocol API mocking made simple** \u2022 REST \u2022 GraphQL \u2022 WebSocket \u2022 UDP\n\n[Features](#features) \u2022 [Quick Start](#quick-start) \u2022 [Documentation](#documentation) \u2022 [Examples](#examples) \u2022 [Contributing](#contributing)\n\n</div>\n\n---\n\n## \ud83c\udfaf Overview\n\nAPI Simulator spins up lifelike backends from a single JSON configuration file. Perfect for frontend development, integration testing, and API prototyping without waiting for backend implementation.\n\n### Key Features\n\n- \ud83d\ude80 **Zero dependencies** - Just Python and a JSON config\n- \ud83d\udd0c **Multi-protocol** - REST, GraphQL, WebSocket, and UDP from one server\n- \ud83d\udcdd **Request-aware templating** - Dynamic responses based on headers, query params, and paths\n- \ud83c\udfad **Realistic behavior** - Rules, delays, errors, and chaos testing\n- \ud83d\udcca **Streaming support** - SSE, NDJSON, and WebSocket broadcasts\n- \ud83d\udd12 **HTTPS/WSS ready** - Built-in TLS support\n- \ud83d\udcd6 **OpenAPI export** - Auto-generated documentation\n\n## \ud83d\ude80 Quick Start\n\n### Installation\n\n```bash\npip install -e .\n```\n\n### Basic Usage\n\n1. **Create a config file** (`config.json`):\n\n```json\n{\n  \"rest\": {\n    \"port\": 3000,\n    \"path\": \"/api\",\n    \"apis\": [\n      {\n        \"method\": \"GET\",\n        \"path\": \"/users/{user_id}\",\n        \"response\": {\n          \"id\": \"{{ path('user_id') }}\",\n          \"name\": \"Test User\",\n          \"created\": \"{{ timestamp() }}\"\n        }\n      }\n    ]\n  }\n}\n```\n\n2. **Start the simulator**:\n\n```bash\napisim run --config config.json\n```\n\n3. **Test your API**:\n\n```bash\ncurl http://localhost:3000/api/users/123\n```\n\n## \ud83d\udcda Documentation\n\n### Table of Contents\n\n- [CLI Commands](#cli-commands)\n- [Configuration](#configuration)\n- [Templating](#templating)\n- [Protocols](#protocols)\n  - [REST API](#rest-api)\n  - [WebSocket](#websocket)\n  - [GraphQL](#graphql)\n  - [UDP Streaming](#udp-streaming)\n- [Advanced Features](#advanced-features)\n\n## \ud83d\udee0\ufe0f CLI Commands\n\n### Server Management\n\n```bash\n# Start server\napisim run --config config.json [options]\n  --templates templates.json  # Template macros\n  --seed 42                   # Deterministic randomness\n  --log-level INFO           # Logging level\n  --certfile cert.pem        # HTTPS/WSS certificate\n  --keyfile key.pem          # HTTPS/WSS key\n\n# Check running servers\napisim status\n\n# Stop servers\napisim stop [--all]\n\n# Validate configuration\napisim validate --config config.json\n\n# Export OpenAPI spec\napisim openapi export --config config.json [--out openapi.json]\n```\n\n## \u2699\ufe0f Configuration\n\n### REST API\n\n```json\n{\n  \"rest\": {\n    \"port\": 3000,\n    \"path\": \"/api/v1\",\n    \"apis\": [\n      {\n        \"method\": \"GET\",\n        \"path\": \"/products/{product_id}\",\n        \"response\": {...},      // JSON response\n        \"text\": \"plain text\",   // Text response\n        \"file\": \"path/to/file\", // File response\n        \"binary_b64\": \"...\",    // Binary response\n        \"stream\": {...},        // NDJSON streaming\n        \"sse\": {...},          // Server-Sent Events\n        \"rules\": {...}         // Conditional behavior\n      }\n    ]\n  }\n}\n```\n\n#### Streaming Responses\n\n**Server-Sent Events (SSE)**:\n```json\n{\n  \"method\": \"GET\",\n  \"path\": \"/events\",\n  \"sse\": {\n    \"interval\": 1,\n    \"event\": \"update\",\n    \"template\": {\"price\": \"{{ random_float(100,200,2) }}\"},\n    \"count\": 10  // null for infinite\n  }\n}\n```\n\n**NDJSON Streaming**:\n```json\n{\n  \"method\": \"GET\",\n  \"path\": \"/stream\",\n  \"stream\": {\n    \"interval\": 0.5,\n    \"template\": {\"seq\": \"{{ counter('seq') }}\"},\n    \"content_type\": \"application/x-ndjson\"\n  }\n}\n```\n\n### WebSocket\n\n```json\n{\n  \"websocket\": {\n    \"port\": 9080,\n    \"path\": \"/ws\",\n    \"apis\": [\n      {\n        \"path\": \"/events\",\n        \"response\": {\"type\": \"ack\"},\n        \"broadcast\": {\n          \"interval\": 5,\n          \"response\": {\"event\": \"{{ counter('events') }}\"}\n        },\n        \"rules\": {\n          \"message.action == 'subscribe'\": {\n            \"response\": {\"subscribed\": true}\n          }\n        }\n      }\n    ]\n  }\n}\n```\n\n### GraphQL\n\n```json\n{\n  \"graphql\": {\n    \"port\": 3000,\n    \"path\": \"/graphql\",\n    \"queries\": [\n      {\n        \"operationName\": \"GetUser\",\n        \"response\": {\"user\": {\"id\": \"123\", \"name\": \"Alice\"}}\n      }\n    ],\n    \"mutations\": [\n      {\n        \"operationName\": \"CreateUser\",\n        \"response\": {\"success\": true, \"id\": \"{{ uuid4() }}\"}\n      }\n    ],\n    \"subscriptions\": [\n      {\n        \"operationName\": \"UserUpdates\",\n        \"interval\": 2,\n        \"response\": {\"user\": {\"updated\": \"{{ timestamp() }}\"}}\n      }\n    ]\n  }\n}\n```\n\n### UDP Broadcasting\n\n```json\n{\n  \"udp\": {\n    \"host\": \"127.0.0.1\",\n    \"port\": 5001,\n    \"apis\": [\n      {\n        \"name\": \"telemetry\",\n        \"broadcast\": {\n          \"interval\": 1,\n          \"response\": {\"temp\": \"{{ random_float(20,30,1) }}\"}\n        }\n      }\n    ]\n  }\n}\n```\n\n## \ud83c\udfa8 Templating\n\n### Built-in Functions\n\n| Function | Description | Example |\n|----------|-------------|---------|\n| `{{ timestamp() }}` | ISO 8601 timestamp | `2024-01-15T10:30:00Z` |\n| `{{ unix_timestamp() }}` | Unix timestamp | `1705315800` |\n| `{{ uuid4() }}` | UUID v4 | `a3bb189e-8bf9-4c90-b8f0-d7d3e7e4d6c1` |\n| `{{ random_int(min, max) }}` | Random integer | `{{ random_int(1, 100) }}` |\n| `{{ random_float(min, max, decimals) }}` | Random float | `{{ random_float(0, 1, 2) }}` |\n| `{{ counter(name, start, step) }}` | Auto-incrementing counter | `{{ counter('order', 1000, 1) }}` |\n| `{{ choice([...]) }}` | Random selection | `{{ choice(['A', 'B', 'C']) }}` |\n\n### Request-Aware Templates\n\nAccess request data in responses:\n\n```json\n{\n  \"response\": {\n    \"path_param\": \"{{ path('user_id') }}\",\n    \"query_param\": \"{{ query('search') }}\",\n    \"header\": \"{{ header('Authorization') }}\",\n    \"body_field\": \"{{ body('email') }}\",\n    \"method\": \"{{ method() }}\"\n  }\n}\n```\n\n### Custom Macros\n\nDefine reusable templates in `templates.json`:\n\n```json\n{\n  \"functions\": {\n    \"order_id\": \"counter('order', 1000, 1)\",\n    \"product\": \"choice(['Widget', 'Gadget', 'Tool'])\",\n    \"price\": \"random_float(10.0, 100.0, 2)\"\n  }\n}\n```\n\n## \ud83c\udfaf Rules & Conditional Behavior\n\n### Rule Conditions\n\n- **Probability**: `\"0.1\"` (10% chance)\n- **Path equality**: `\"path.user_id == '123'\"`\n- **Query params**: `\"query.debug == 'true'\"`\n- **Headers**: `\"header.X-Test == 'yes'\"`\n- **Body fields**: `\"body.amount > 100\"`\n\n### Actions\n\n```json\n{\n  \"rules\": {\n    \"query.test == 'error'\": {\n      \"status\": 500,\n      \"response\": {\"error\": \"Test error\"},\n      \"headers\": {\"X-Error\": \"true\"}\n    },\n    \"header.X-Slow == 'true'\": {\n      \"delay\": \"2s\"\n    },\n    \"0.05\": {\n      \"ignore\": true  // 5% drop rate\n    }\n  }\n}\n```\n\n## \ud83e\uddea Testing\n\n### Running Tests\n\n```bash\n# All tests\npytest tests/ -v\n\n# Specific protocols\npytest tests/test_protocols.py::TestRESTProtocol -v\npytest tests/test_e2e_protocols.py -v\n\n# With coverage\npytest tests/ --cov=api_simulator\n```\n\n### Test Structure\n\n```\ntests/\n\u251c\u2500\u2500 test_cli.py           # CLI command tests\n\u251c\u2500\u2500 test_protocols.py     # Protocol unit tests\n\u2514\u2500\u2500 test_e2e_protocols.py # End-to-end with lifespan\n```\n\n## \ud83d\udcd6 Examples\n\n### Complete E-Commerce API\n\nSee [`examples/config.json`](examples/config.json) for a full example with:\n- Product catalog with search\n- Order streaming\n- Real-time price updates (SSE)\n- WebSocket order events\n- GraphQL customer queries\n- UDP inventory feeds\n\n### Testing Different Protocols\n\nAfter starting the server with `apisim run --config examples/config.json`:\n\n**REST API Tests:**\n```bash\n# Basic GET endpoint\ncurl http://localhost:3000/api/v1/status\n\n# Path parameters, query strings, and headers\ncurl \"http://localhost:3000/api/v1/products/PROD-123?q=search\" \\\n  -H \"X-Session-Id: test-session\"\n\n# SSE streaming (real-time price updates)\ncurl -N http://localhost:3000/api/v1/prices/sse\n\n# NDJSON streaming \ncurl -N http://localhost:3000/api/v1/stream/orders\n```\n\n**GraphQL Tests:**\n```bash\n# Query\ncurl -X POST http://localhost:3000/graphql \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"operationName\":\"GetCustomer\"}'\n\n# Mutation\ncurl -X POST http://localhost:3000/graphql \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"operationName\":\"CreateOrder\"}'\n\n# List available operations\ncurl http://localhost:3000/openapi.json | jq '.paths.\"/graphql\"'\n```\n\n**WebSocket Tests:**\n```bash\n# Using wscat (npm install -g wscat)\nwscat -c ws://localhost:9080/realtime/events\n> {\"action\":\"subscribe\"}\n\n# Using Python\npython3 -c \"\nimport asyncio, websockets, json\nasync def test():\n    async with websockets.connect('ws://localhost:9080/realtime/events') as ws:\n        await ws.send(json.dumps({'action': 'subscribe'}))\n        print(await ws.recv())\nasyncio.run(test())\n\"\n\n# GraphQL Subscriptions\npython3 -c \"\nimport asyncio, websockets, json\nasync def test():\n    async with websockets.connect('ws://localhost:9080/realtime/graphql') as ws:\n        await ws.send(json.dumps({'type': 'connection_init'}))\n        print(await ws.recv())\n        await ws.send(json.dumps({'id': '1', 'type': 'subscribe', \n                                 'payload': {'operationName': 'PriceUpdates'}}))\n        print(await ws.recv())\nasyncio.run(test())\n\"\n```\n\n**UDP Listener:**\n```bash\npython3 -c \"\nimport socket, struct, msgpack\ns = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)\ns.bind(('127.0.0.1', 5001))\nprint('Listening on 127.0.0.1:5001...')\nwhile True:\n    pkt, _ = s.recvfrom(65536)\n    magic, ts, n = struct.unpack('>IIH', pkt[:10])\n    print(f'Magic: 0x{magic:X}, Payload:', msgpack.unpackb(pkt[10:], raw=False))\n\"\n```\n\n## \ud83d\udd0c API Documentation\n\nWhen running, access auto-generated API docs at:\n\n- **Swagger UI**: http://localhost:3000/docs\n- **ReDoc**: http://localhost:3000/redoc\n- **OpenAPI JSON**: http://localhost:3000/openapi.json\n\n## \ud83d\udc33 Docker\n\n```dockerfile\nFROM python:3.11-slim\nWORKDIR /app\nCOPY . .\nRUN pip install -e .\nCMD [\"apisim\", \"run\", \"--config\", \"/config/config.json\"]\n```\n\n```bash\ndocker build -t api-simulator .\ndocker run -p 3000:3000 -p 9080:9080 \\\n  -v $(pwd)/examples:/config \\\n  api-simulator\n```\n\n## \ud83e\udd1d Contributing\n\nWe welcome contributions! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.\n\n### Development Setup\n\n```bash\n# Clone repository\ngit clone https://github.com/yourusername/api-simulator\ncd api-simulator\n\n# Create virtual environment\npython -m venv venv\nsource venv/bin/activate  # or `venv\\Scripts\\activate` on Windows\n\n# Install with dev dependencies\npip install -e \".[test]\"\n\n# Run tests\npytest tests/ -v\n\n# Check code style\nruff check src/\n```\n\n## \ud83d\udcdd License\n\nMIT License - see [LICENSE](LICENSE) file for details.\n\n## \ud83d\ude4f Acknowledgments\n\nBuilt with:\n- [FastAPI](https://fastapi.tiangolo.com/) - REST/GraphQL server\n- [websockets](https://websockets.readthedocs.io/) - WebSocket support\n- [msgpack](https://msgpack.org/) - Binary serialization\n- [Pydantic](https://pydantic-docs.helpmanual.io/) - Data validation\n\n## \ud83d\udcee Support\n\n- \ud83d\udce7 Email: support@example.com\n- \ud83d\udcac Discord: [Join our server](https://discord.gg/example)\n- \ud83d\udc1b Issues: [GitHub Issues](https://github.com/yourusername/api-simulator/issues)\n\n---\n\n<div align=\"center\">\nMade with \u2764\ufe0f by the API Simulator Team\n</div>\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Multi-protocol API mocking made simple - REST, GraphQL, WebSocket, UDP from a single JSON config",
    "version": "0.3.0",
    "project_urls": {
        "Documentation": "https://github.com/yourusername/api-simulator#documentation",
        "Homepage": "https://github.com/yourusername/api-simulator",
        "Issues": "https://github.com/yourusername/api-simulator/issues",
        "Repository": "https://github.com/yourusername/api-simulator.git"
    },
    "split_keywords": [
        "api",
        " mock",
        " simulator",
        " rest",
        " graphql",
        " websocket",
        " udp",
        " testing",
        " development"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "09ea2c0e208f3684596b5de2a501e9860fdbae46b6159f04dc48d626b92a0e9b",
                "md5": "f1a7e61f6918f5434777a1aa0a914e7f",
                "sha256": "035e4c6c02b6ccfcd461e4dda40094252f05dfc0a5220600ad0692d7cb47dbe0"
            },
            "downloads": -1,
            "filename": "api_simulator-0.3.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "f1a7e61f6918f5434777a1aa0a914e7f",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.9",
            "size": 23229,
            "upload_time": "2025-08-16T01:24:36",
            "upload_time_iso_8601": "2025-08-16T01:24:36.272634Z",
            "url": "https://files.pythonhosted.org/packages/09/ea/2c0e208f3684596b5de2a501e9860fdbae46b6159f04dc48d626b92a0e9b/api_simulator-0.3.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "c1bdabbce2400e5d2e0f68d977075ac41c559c709b4994028a2994619147c2bb",
                "md5": "0e6f8c170374aa496f62a1463445ab96",
                "sha256": "1e8f6ab4a80a37891a19a19e0d56992be93ea889a81571b9d8866c2655b31997"
            },
            "downloads": -1,
            "filename": "api_simulator-0.3.0.tar.gz",
            "has_sig": false,
            "md5_digest": "0e6f8c170374aa496f62a1463445ab96",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.9",
            "size": 33090,
            "upload_time": "2025-08-16T01:24:37",
            "upload_time_iso_8601": "2025-08-16T01:24:37.279923Z",
            "url": "https://files.pythonhosted.org/packages/c1/bd/abbce2400e5d2e0f68d977075ac41c559c709b4994028a2994619147c2bb/api_simulator-0.3.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-08-16 01:24:37",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "yourusername",
    "github_project": "api-simulator#documentation",
    "github_not_found": true,
    "lcname": "api-simulator"
}
        
Elapsed time: 1.74812s