Serverul te apelează pe tine
Un server web în Python (modulul standard http.server) este construit din clase handler: creezi o subclasă a lui BaseHTTPRequestHandler și scrii o metodă do_GET. Serverul acceptă conexiunile și apelează metoda ta o dată pentru fiecare cerere — self.path și self.headers conțin cererea, iar send_response, send_header și self.wfile construiesc răspunsul.
Un server real apelează serve_forever() pe un port fix și rulează la nesfârșit. Exemplele de aici aleg portul 0 — un port liber aleatoriu — și rulează serve_forever într-un fir de execuție în fundal, astfel încât fiecare exemplu își pornește serverul, îl folosește și se termină singur. De asemenea, ele suprascriu log_message cu o metodă goală: clasa de bază afișează o linie de jurnal cu marcaj de timp pentru fiecare cerere, iar demonstrațiile au nevoie de o ieșire curată și stabilă.
Primul handler
Cel mai mic handler posibil scrie o linie de text. Tot ce face un API — JSON, coduri de stare, rutare — se întâmplă în interiorul unei metode cu aceeași formă.
Salut de la un handler
Handler-ul scrie în self.wfile; clientul citește exact acel conținut drept corp al răspunsului, cu linia de stare aleasă prin send_response(200).
Ieșire: program Python complet
import threading
import urllib.request
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
class HelloHandler(BaseHTTPRequestHandler):
# Serverul apelează această metodă o dată pentru fiecare cerere GET.
def do_GET(self):
self.send_response(200)
self.send_header("Content-Type", "text/plain")
self.end_headers()
self.wfile.write(b"salut de la server\n")
def log_message(self, fmt, *args):
pass # fără linii de jurnal pentru cereri în ieșirea demonstrației
server = ThreadingHTTPServer(("127.0.0.1", 0), HelloHandler)
port = server.server_address[1]
threading.Thread(target=server.serve_forever, daemon=True).start()
with urllib.request.urlopen(f"http://127.0.0.1:{port}/") as resp:
print("stare:", resp.status, resp.reason)
print("corp: ", resp.read().decode(), end="")
server.shutdown()
Răspunsul cu JSON
Un handler de API face trei lucruri: alege un cod de stare, setează antetul Content-Type și scrie datele codificate — json.dumps construiește textul, iar self.wfile.write trimite octeții.
Ordinea contează: mai întâi send_response, apoi antetele, apoi end_headers și abia după aceea corpul.
Un endpoint JSON
Handler-ul pune un dicționar direct în răspuns. Clientul primește JSON valid și tipul de conținut corect — acesta este scheletul fiecărui endpoint din restul acestui grup.
Ieșire: program Python complet
import json
import threading
import urllib.request
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
class UserHandler(BaseHTTPRequestHandler):
def do_GET(self):
body = json.dumps({"id": 1, "name": "Ana"}) + "\n"
self.send_response(200) # mai întâi codul de stare
self.send_header("Content-Type", "application/json")
self.end_headers() # antetele încheiate
self.wfile.write(body.encode()) # apoi corpul
def log_message(self, fmt, *args):
pass
server = ThreadingHTTPServer(("127.0.0.1", 0), UserHandler)
port = server.server_address[1]
threading.Thread(target=server.serve_forever, daemon=True).start()
with urllib.request.urlopen(f"http://127.0.0.1:{port}/user") as resp:
print("stare:", resp.status, resp.reason)
print("tip: ", resp.headers["Content-Type"])
print("corp: ", resp.read().decode(), end="")
server.shutdown()