How to Build a Mock REST GET Endpoint Handler in Python

Create a lightweight mock REST GET server in Python using the standard library, with a dict-based route registry that maps paths to handler functions and returns JSON responses with proper HTTP status codes.

Medium Python 3.9+ Aug 9, 2026 API design & gRPC 14 views 0 copies

Python code

42 lines
Python 3.9+
from http.server import BaseHTTPRequestHandler, HTTPServer
import json

# Mock API handler registry
def handle_users():
    return {"status": "ok", "data": [{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}]}

def handle_products():
    return {"status": "ok", "data": [{"id": 101, "name": "Laptop", "price": 999.99}]}

def handle_not_found():
    return {"status": "error", "message": "Endpoint not found"}, 404

# Mock route map (dict of {'path': handler})
routes = {
    "/api/users": handle_users,
    "/api/products": handle_products,
}

class MockHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        # Look up handler by path
        handler = routes.get(self.path, handle_not_found)
        result = handler()
        
        # Support handlers returning (data, status_code) tuples
        if isinstance(result, tuple):
            data, status = result
        else:
            data, status = result, 200
        
        self.send_response(status)
        self.send_header("Content-Type", "application/json")
        self.end_headers()
        self.wfile.write(json.dumps(data).encode())

if __name__ == "__main__":
    # Test the mock server in-process
    server = HTTPServer(("localhost", 8000), MockHandler)
    print("Mock server running on port 8000")
    print("Endpoints: /api/users, /api/products")
    server.serve_forever()

Output

stdout
Mock server running on port 8000
Endpoints: /api/users, /api/products

How it works

The BaseHTTPRequestHandler subclass defines the do_GET method, which is called for every incoming GET request. The routes dict maps URL paths directly to handler functions, so looking up a handler is just a dict .get() call. Handlers return either a dict (interpreted as status 200) or a tuple of (data, status_code), allowing flexible error responses. The json.dumps() call serializes the response data, and wfile.write() sends the bytes over the HTTP connection.

Common mistakes

  • Forgetting to call `end_headers()` before writing the response body
  • Returning handlers that don't handle unknown paths gracefully (missing 404 fallback)
  • Not encoding the JSON string with `.encode()` before writing to `wfile`

Variations

  1. Use `Flask` and its `@app.route` decorator for a more feature-rich mock API
  2. Load routes from a JSON config file to make the mock server data-driven

Real-world use cases

  • Stubbing a backend API during frontend development so UI teams can work independently of backend progress.
  • Creating a test double for integration tests to simulate third-party service responses without network calls.
  • Building a lightweight prototype server to demonstrate API contracts to stakeholders before the real implementation is complete.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from API design & gRPC

Related tutorials and quizzes for this topic.