Version API by Accept Header with Vendor Media Types in Python
Build a mock HTTP server that routes to API versions by parsing vendor-specific Accept headers in Python.
Python code
40 linesfrom http.client import HTTPMessage
from http.server import BaseHTTPRequestHandler, HTTPServer
class VendorVersionHandler(BaseHTTPRequestHandler):
def do_GET(self):
accept = self.headers.get("Accept", "")
version = "v1"
if "application/vnd.myapi.v2+json" in accept:
version = "v2"
elif "application/vnd.myapi.v3+json" in accept:
version = "v3"
body = f'{{"version": "{version}"}}'.encode()
self.send_response(200)
self.send_header("Content-Type", "application/json")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
def log_message(self, format, *args):
pass
def parse_accept(accept_header):
if "application/vnd.myapi.v3+json" in accept_header:
return "v3"
if "application/vnd.myapi.v2+json" in accept_header:
return "v2"
return "v1"
if __name__ == "__main__":
tests = [
"application/json",
"application/vnd.myapi.v2+json",
"application/vnd.myapi.v3+json, application/json",
]
for accept in tests:
print(f"{accept!r} -> {parse_accept(accept)}")
Output
'application/json' -> v1
'application/vnd.myapi.v2+json' -> v2
'application/vnd.myapi.v3+json, application/json' -> v3
How it works
This example implements API version negotiation using the Accept header with vendor media types. The parse_accept function checks for exact substring matches of application/vnd.myapi.vN+json and returns the corresponding version string. In the HTTP handler, do_GET reads the header and echoes the version in a JSON response. Because the logic is centralized in parse_accept, the same function can be reused in tests or outside the server. The log_message override keeps console output clean so the printed results stay focused.
Common mistakes
- Relying on simple `startswith` or ignoring the Accept header entirely can break version negotiation.
- Forgetting to check for more specific versions before fallbacks — order matters when multiple vendor types are present.
- Not handling missing Accept header, which should default to the oldest version.
Variations
- Use `acceptheader.parse` from the `accept` library for robust RFC-compliant parsing.
- Extract the version via regex like `re.search(r'v(\d+)\+json', accept)` for dynamic version lists.
Real-world use cases
- Backend APIs decouple breaking changes by letting clients opt into v2 or v3 via explicit Accept headers.
- Mobile app releases can target different API versions without changing URLs during gradual rollout.
- Gateway or proxy layer reads the vendor Accept header to route requests to different microservice deployments.
Sponsored
More from API design & gRPC
- Build a Bulk Array POST Mock Server in Python medium
- Build a Mock REST API with PUT and GET in Python medium
- Convert Protobuf to JSON and Dict in Python easy
- Create a Data Helper in Python for gRPC-style APIs easy
- Format data in Python using dataclasses like gRPC messages easy
- Generate an OpenAPI Spec from Mock Routes in Python easy
Keep learning
Related tutorials and quizzes for this topic.