Skip to content

Commit aad7852

Browse files
committed
feat: 👔 add RESTful API
1 parent e1dff83 commit aad7852

File tree

1 file changed

+95
-0
lines changed

1 file changed

+95
-0
lines changed

playground/client_server/rest_api.py

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import json
2+
from http.server import BaseHTTPRequestHandler, HTTPServer
3+
from typing import Any
4+
5+
Book = dict[str, Any]
6+
books: list[Book] = [
7+
{"id": 1, "title": "The Great Gatsby", "author": "F. Scott Fitzgerald"},
8+
{"id": 2, "title": "To Kill a Mockingbird", "author": "Harper Lee"},
9+
{"id": 3, "title": "1984", "author": "George Orwell"},
10+
{"id": 4, "title": "The Catcher in the Rye", "author": "J.D. Salinger"},
11+
{
12+
"id": 5,
13+
"title": "Foley Is Good: And the Real World Is Faker Than Wrestling",
14+
"author": "Mick Foley",
15+
},
16+
{
17+
"id": 6,
18+
"title": "Hitman: My Real Life in the Cartoon World of Wrestling",
19+
"author": "Bret Hart",
20+
},
21+
{
22+
"id": 7,
23+
"title": "Undisputed: How to Become World Champion in 1,372 Easy Steps",
24+
"author": "Chris Jericho",
25+
},
26+
{
27+
"id": 8,
28+
"title": "Have A Nice Day: A Tale of Blood and Sweatsocks",
29+
"author": "Mick Foley",
30+
},
31+
]
32+
33+
34+
class RequestHandler(BaseHTTPRequestHandler):
35+
def _handle_get_books(self) -> None:
36+
self._set_response()
37+
self.wfile.write(json.dumps(books).encode("utf-8"))
38+
39+
def _handle_post_book(self) -> None:
40+
content_length = int(self.headers["Content-Length"])
41+
if content_length == 0:
42+
self._set_response(400)
43+
self.wfile.write(json.dumps({"error": "No data provided"}).encode("utf-8"))
44+
return
45+
post_data = self.rfile.read(content_length)
46+
try:
47+
new_book: Book = json.loads(post_data)
48+
if (
49+
"id" not in new_book
50+
or "title" not in new_book
51+
or "author" not in new_book
52+
):
53+
raise ValueError("Missing fields")
54+
books.append(new_book)
55+
self._set_response(201)
56+
self.wfile.write(json.dumps(new_book).encode("utf-8"))
57+
except (json.JSONDecodeError, ValueError) as e:
58+
self._set_response(400)
59+
self.wfile.write(
60+
json.dumps({"error": "Invalid data", "message": str(e)}).encode("utf-8")
61+
)
62+
63+
def _set_response(self, status_code: int = 200) -> None:
64+
self.send_response(status_code)
65+
self.send_header("Content-type", "application/json")
66+
self.end_headers()
67+
68+
def do_GET(self) -> None:
69+
if self.path == "/books":
70+
self._handle_get_books()
71+
else:
72+
self._set_response(404)
73+
self.wfile.write(json.dumps({"error": "Not Found"}).encode("utf-8"))
74+
75+
def do_POST(self) -> None:
76+
if self.path == "/books":
77+
self._handle_post_book()
78+
else:
79+
self._set_response(404)
80+
self.wfile.write(json.dumps({"error": "Not Found"}).encode("utf-8"))
81+
82+
83+
def run(
84+
server_class: type[HTTPServer] = HTTPServer,
85+
handler_class: type[BaseHTTPRequestHandler] = RequestHandler,
86+
port: int = 8000,
87+
) -> None:
88+
server_address = ("", port)
89+
httpd = server_class(server_address, handler_class)
90+
print(f"Starting server on port {port}...")
91+
httpd.serve_forever()
92+
93+
94+
if __name__ == "__main__":
95+
run()

0 commit comments

Comments
 (0)