Build a Mock REST API with PUT and GET in Python
A minimal mock REST server implementing idempotent PUT for resource replacement and GET for retrieval, built with Python's http.server module.
Python code
49 linesfrom http.server import BaseHTTPRequestHandler, HTTPServer
import json
from urllib.parse import urlparse
mock_db = {}
class MockAPIHandler(BaseHTTPRequestHandler):
def do_PUT(self):
parsed = urlparse(self.path)
resource_id = parsed.path.strip("/").split("/")[-1]
content_length = int(self.headers.get("Content-Length", 0))
payload = json.loads(self.rfile.read(content_length) or b"{}")
mock_db[resource_id] = payload
self.send_response(200)
self.send_header("Content-Type", "application/json")
self.end_headers()
self.wfile.write(json.dumps({
"id": resource_id,
"data": payload,
"message": "Resource replaced successfully (idempotent)"
}).encode())
def do_GET(self):
parsed = urlparse(self.path)
resource_id = parsed.path.strip("/").split("/")[-1]
if resource_id in mock_db:
self.send_response(200)
self.send_header("Content-Type", "application/json")
self.end_headers()
self.wfile.write(json.dumps(mock_db[resource_id]).encode())
else:
self.send_response(404)
self.end_headers()
def log_message(self, format, *args):
pass
def run_server():
server = HTTPServer(("localhost", 8000), MockAPIHandler)
print("Mock REST server running on http://localhost:8000")
server.serve_forever()
if __name__ == "__main__":
run_server()
Output
Mock REST server running on http://localhost:8000
# Client requests:
curl -X PUT http://localhost:8000/users/42 -d '{"name": "Alice"}'
{"id": "42", "data": {"name": "Alice"}, "message": "Resource replaced successfully (idempotent)"}
curl http://localhost:8000/users/42
{"name": "Alice"}
curl http://localhost:8000/users/99
(404 response)
# Repeating the same PUT returns the same 200 response — idempotent behavior:
How it works
The do_PUT method reads the request body with Content-Length to avoid blocking, then parses it as JSON. Storing the payload in a dictionary keyed by the resource ID makes replacement idempotent — repeating the same PUT yields identical results. The do_GET handler looks up the ID and returns 404 for missing resources. All state lives in-memory, so the mock resets on restart, which is ideal for tests or local prototyping.
Common mistakes
- Forgetting to handle `Content-Length` when reading the request body, causing hangs or partial reads
- Assuming the resource ID is always numeric; the URL path parsing may need validation
- Not setting `Content-Type` headers, leading to clients misinterpreting responses
Variations
- Use Flask or FastAPI for more routing features, validation, and auto-generated docs
- Add DELETE support by removing the key from the dictionary
Real-world use cases
- Stubbing a backend API during frontend development so UI work isn't blocked by service availability.
- Providing a throwaway test double in integration tests to verify client retry and error-handling logic.
- Simulating a resource store for acceptance tests of PUT idempotency contract requirements.
Sponsored
More from API design & gRPC
- Build a Bulk Array POST Mock Server 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
- How to Add HATEOAS Links to a Python API Response easy
Keep learning
Related tutorials and quizzes for this topic.