How to Mock Service Versioning URI in Python
Run a minimal HTTP server in Python that routes requests to different versions of a service URI like /v1/users vs /v2/users.
Python code
31 linesfrom http.server import HTTPServer, BaseHTTPRequestHandler
import json
class VersionedHandler(BaseHTTPRequestHandler):
def _send_json(self, payload, status=200):
body = json.dumps(payload).encode("utf-8")
self.send_response(status)
self.send_header("Content-Type", "application/json")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
def do_GET(self):
if self.path.startswith("/v1/users"):
self._send_json({"api_version": "v1", "endpoint": "users"})
elif self.path.startswith("/v2/users"):
self._send_json({"api_version": "v2", "endpoint": "users"})
else:
self._send_json({"error": "not found"}, status=404)
def run_server(port=8000):
server = HTTPServer(("127.0.0.1", port), VersionedHandler)
print(f"Serving on http://127.0.0.1:{port}")
server.handle_request() # handle one request for demo
server.server_close()
if __name__ == "__main__":
run_server()
Output
Serving on http://127.0.0.1:8000
How it works
The code subclasses BaseHTTPRequestHandler to implement a tiny, dependency-free HTTP server. Each incoming GET request is inspected via self.path, and simple startswith checks route /v1/users and /v2/users to different handler branches. The _send_json helper centralizes JSON serialization, headers, and writing the response body, so every endpoint returns consistent JSON. Only one request is handled before the server closes, which keeps this demo deterministic for testing or CI. Starting the server from if __name__ == "__main__" lets you import the handler elsewhere without accidentally running a server.
Common mistakes
- Forgetting to set Content-Length, which can cause clients to hang waiting for the response body.
- Using exact equality instead of startswith, breaking requests with trailing slashes or query strings like /v2/users?page=1.
- Attempting multiple handle_request calls in a loop without threading, which would serve requests serially.
- Not URL-decoding the path when version segments might contain encoded characters.
Variations
- Use `server.serve_forever()` in a background thread to handle multiple requests concurrently (still simple).
- Check version by parsing `pathlib.PurePosixPath(self.path)` segments instead of string startswith for more robust routing.
Real-world use cases
- Local smoke tests of API endpoints before deploying versioned services.
- Stub backends for frontend development or integration tests when real services are unavailable.
- Quick demos or educational examples that show how versioned route matching works in microservice gateways.
Sponsored
More from Microservices patterns
- BFF aggregation pattern: combine multiple service responses in Python easy
- Backward Compatible Schema Evolution in Python medium
- Bulkhead Thread Pool per Service Mock in Python medium
- CQRS with Separate Read and Write Repositories in Python medium
- Cache-Aside Pattern in Python: Per-Service Mock easy
- Consumer Driven Contract Pact Mock in Python medium
Keep learning
Related tutorials and quizzes for this topic.