ЁЯПл The SchoolтА║ЁЯПв APIsтА║ЁЯФА рдзрдбрд╛ 11 тАФ REST рдЪреНрдпрд╛ рдкрд▓реАрдХрдбреЗ: рдЬреЗрд╡реНрд╣рд╛ рдХрд╛рдЙрдВрдЯрд░ рддреБрдореНрд╣рд╛рд▓рд╛ рдкрд░рдд рдХреЙрд▓ рдХрд░рддреЛ
ЁЯЦ╝я╕П See the drawing + lab ЁЯПа Course home ЁЯМ┐ Branch on GitHub тЬПя╕П View source
ЁЯЦ╝я╕П рдЖрдХреГрддреА рдЖрдгрд┐ labThe drawing + lab рдкреВрд░реНрдг рдкрд╛рдирд╛рд╡рд░ рдЙрдШрдбрд╛ тЖЧOpen full page тЖЧ

ЁЯФА рдзрдбрд╛ 11 тАФ REST рдЪреНрдпрд╛ рдкрд▓реАрдХрдбреЗ: рдЬреЗрд╡реНрд╣рд╛ рдХрд╛рдЙрдВрдЯрд░ рддреБрдореНрд╣рд╛рд▓рд╛ рдкрд░рдд рдХреЙрд▓ рдХрд░рддреЛ

ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 12 рдкреИрдХреА рдзрдбрд╛ 11 ┬╖ рдорд╛рдЧреАрд▓: lesson-10-rate-limits-caching ┬╖ рдкреБрдвреАрд▓: lesson-12-testing-docs-gateway


ЁЯУж рдпрд╛ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рдХрд╛рдп рдЖрд╣реЗ

рдзрдбреЗ 01тАУ10, рдЖрдгрд┐ рддреНрдпрд╛рд╕реЛрдмрдд рдХрд╛рдЙрдВрдЯрд░рдЪреЗ рдЗрддрд░ рдЖрдХрд╛рд░ тАФ GraphQL, gRPC, webhooks, events тАФ рдЖрдгрд┐ рддреНрдпрд╛рддрд▓рд╛ рдПрдХ рдирд┐рд╡рдбрдгреНрдпрд╛рдЪрд╛ рдирд┐рдпрдо. рдЦрд▒реНрдпрд╛ files:

ЁЯФА рд╕рдВрдкреВрд░реНрдг рдирдХрд╛рд╢рд╛: рд╣рд╛ рдзрдбрд╛ рдиреЗрд╣рдореА рднреЗрдЯрдгрд╛рд░реЗ рдЪрд╛рд░ рдЖрдХрд╛рд░ рд╢рд┐рдХрд╡рддреЛ. рдЗрддрд░ рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░рдХрд╛рд░ тАФ SOAP, tRPC, OData, WebRTC, queues, event streams, batch files, рдЖрдгрд┐ network рд▓рд╛ рдХрдзреАрдЪ рди рд╢рд┐рд╡рдгрд╛рд░реЗ APIs (libraries, system calls, database drivers) тАФ рдореНрд╣рдгрдЬреЗ рдзрдбрд╛ 15 тАФ рдкреНрд░рддреНрдпреЗрдХ API рдкреНрд░рдХрд╛рд░: рдПрдХ рдореБрдЦреНрдп рддрдХреНрддрд╛, рдЪрд╛рд░ рдХреБрдЯреБрдВрдмреЗ рдЖрдгрд┐ рдПрдХ рдирд┐рд░реНрдгрдп-рдорд╛рд░реНрдЧрджрд░реНрд╢рди.

ЁЯзТ 5 рд╡рд░реНрд╖рд╛рдВрдЪреНрдпрд╛ рдореБрд▓рд╛рд▓рд╛ рд╕рдордЬрд╛рд╡рд▓реНрдпрд╛рд╕рд╛рд░рдЦреЗ

REST рд╣рд╛ рдХрд╛рдЙрдВрдЯрд░рдЪрд╛ рдПрдХ рдкреНрд░рдХрд╛рд░ рдЖрд╣реЗ: рдирд╛рд╡реЗ рджрд┐рд▓реЗрд▓реЗ drawers, рдард░рд▓реЗрд▓реНрдпрд╛ slips. рдЖрдгрдЦреА рддреАрди рдкреНрд░рдХрд╛рд░ рдЖрд╣реЗрдд, рдЖрдгрд┐ рдкреНрд░рддреНрдпреЗрдХрд╛рдорд╛рдЧреЗ рдЦрд░реЗ рдХрд╛рд░рдг рдЖрд╣реЗ:

рдирд┐рд╡рдб рдореНрд╣рдгрдЬреЗ рдлреЕрд╢рди рдирд╡реНрд╣реЗ: рдЖрдХрд╛рд░ caller рдиреБрд╕рд╛рд░ рдард░рддреЛ.

ЁЯЧ║я╕П рдЖрдХреГрддреА

flowchart LR
    rest["ЁЯЧДя╕П REST<br/>nouns + verbs, cacheable тАФ public, simple"]
    gql["ЁЯзй GraphQL<br/>ask for exactly these fields тАФ one UI, many shapes"]
    grpc["тЪб gRPC<br/>typed, binary, streaming тАФ service тЖФ service"]
    hook["ЁЯУг webhooks<br/>the counter calls you back on events"]
    ev["ЁЯУм events / queues<br/>'tell me when', replayable"]
    caller["ЁЯзн the shape follows the caller"] --> rest & gql & grpc & hook & ev

тЭУ рдХрд╛рдп

ЁЯдФ рдХрд╛

рдХрд╛рд░рдг рдЯреАрдореНрд╕ рдлреЕрд╢рди рдкрд╛рд╣реВрди рдЖрдХрд╛рд░ рдирд┐рд╡рдбрддрд╛рдд рдЖрдгрд┐ рд╡рд░реНрд╖рд╛рдиреБрд╡рд░реНрд╖реЗ рддреНрдпрд╛рдЪреА рдХрд┐рдВрдордд рдореЛрдЬрддрд╛рдд: рджреЛрди endpoints рдЕрд╕рд▓реЗрд▓реНрдпрд╛ service рд╕рд╛рдареА GraphQL API, browsers рдирд╛ call рдХрд░рд╛рдпрдЪрд╛ рдЕрд╕рд▓реЗрд▓реНрдпрд╛ public API рд╕рд╛рдареА gRPC, рдЬрд┐рдереЗ webhook рдлрдХреНрдд рдПрдХрд╛ рдиреЛрдВрджрдгреАрдЪреНрдпрд╛ рдЕрдВрддрд░рд╛рд╡рд░ рд╣реЛрддрд╛ рддрд┐рдереЗ polling. рдЪрд╛рд░ рдЖрдХрд╛рд░ рдЖрдгрд┐ рдПрдХ рдирд┐рдпрдо рдорд╛рд╣реАрдд рдЕрд╕рд▓рд╛, рдХреА рдирд┐рд╡рдб рдмрд╣реБрддреЗрдХ рд╡реЗрд│рд╛ рдЙрдШрдб рдЕрд╕рддреЗ.

ЁЯФз рдХрд╕реЗ (рдпрд╛ repo рдордзреНрдпреЗ)

POST /v1/webhooks {"url": тАж} рдПрдХ URL рдиреЛрдВрджрд╡рддреЛ; school_api.py рдордзрд▓рд╛ notify() рдпрд╢рд╕реНрд╡реА рдкреНрд░рд╡реЗрд╢рд╛рдирдВрддрд░ рдкреНрд░рддреНрдпреЗрдХ рдиреЛрдВрджрд╡рд▓реЗрд▓реНрдпрд╛ URL рд╡рд░ student.created event POST рдХрд░рддреЛ тАФ рдЖрдгрд┐ рдЕрдкрдпрд╢ рдЧрд┐рд│реВрди рдЯрд╛рдХрддреЛ, рдХрд╛рд░рдг рдмрдВрдж рдкрдбрд▓реЗрд▓реНрдпрд╛ webhook рдореБрд│реЗ рдХрд╛рдЙрдВрдЯрд░ рдХрдзреАрдЪ рдмрд┐рдШрдбрддрд╛ рдХрд╛рдорд╛ рдирдпреЗ. api/webhook_receiver.py рд╣реА рджреБрд╕рд░реА рдмрд╛рдЬреВ рдЖрд╣реЗ: рдЬреЗ рдпреЗрддреЗ рддреЗ рдЫрд╛рдкрдгрд╛рд░рд╛ 15 рдУрд│реАрдВрдЪрд╛ server.

ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛

# A) six shapes, one dataset тАФ REST ┬╖ JSON-RPC ┬╖ GraphQL ┬╖ long polling ┬╖ SSE ┬╖ WebSocket
python3 api/api_types.py &                                           # :8081
python3 api/types_client.py                                          # every byte of all six, printed
# read the differences: whole resource vs chosen fields vs an error inside a 200 vs a held request vs a stream vs a socket

# B) the webhook, from both sides:
python3 api/webhook_receiver.py &                                    # terminal 3: your phone rings here on :9090
B=http://127.0.0.1:8080/v1; K='X-API-Key: hall-pass-123'; J='Content-Type: application/json'
curl -s -X POST $B/webhooks -H "$J" -d '{"url":"http://127.0.0.1:9090/hook"}'
curl -s -X POST $B/students -H "$K" -H "$J" -d '{"name":"Zoya","class":"3B"}' > /dev/null
# terminal 3 prints: ЁЯУг webhook received: {'event': 'student.created', 'student': {...}}
kill %1                                                              # now the receiver is dead тАФ
curl -s -X POST $B/students -H "$K" -H "$J" -d '{"name":"Yash","class":"3A"}' | head -c 80   # still 201: the counter survives

тЬЕ рддрдкрд╛рд╕рд╛ тАФ рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд╛рдп рджрд┐рд╕рд╛рдпрд▓рд╛ рд╣рд╡реЗ

types_client.py рдирд╛рд╡реЗ рджрд┐рд▓реЗрд▓реЗ рд╕рд╣рд╛ рд╡рд┐рднрд╛рдЧ рдЫрд╛рдкрддреЛ рдЖрдгрд┐ тЬЕ six shapes, one dataset рдиреЗ рд╕рдВрдкрддреЛ: REST рдкреВрд░реНрдг resources рдкрд░рдд рджреЗрддреЗ, JSON-RPC error рдПрдХрд╛ 200 рдЪреНрдпрд╛ рдЖрдд рдкрд░рдд рджреЗрддреЗ, GraphQL рдлрдХреНрдд рддреБрдореНрд╣реА рд╕рд╛рдВрдЧрд┐рддрд▓реЗрд▓реЗ fields рджреЗрддреЗ, long polling ~0.4 s рдЙрд╢рд┐рд░рд╛ рдПрдХрд╛ event рд╕рд╣ рдЙрддреНрддрд░ рджреЗрддреЗ, SSE id:/event:/data: frames рдЫрд╛рдкрддреЗ (рдЖрдгрд┐ рддреБрдореНрд╣реА Last-Event-ID: 0 рдкрд╛рдард╡рд▓реНрдпрд╛рд╡рд░ рдЗрддрд┐рд╣рд╛рд╕ replay рдХрд░рддреЗ), рдЖрдгрд┐ WebSocket рджреЛрдиреНрд╣реА рджрд┐рд╢рд╛рдВрдиреА echo рдХрд░рдгреНрдпрд╛рдЖрдзреА 101 Switching Protocols рджрд╛рдЦрд╡рддреЗ.

Receiver рдирд╡реНрдпрд╛ рд╡рд┐рджреНрдпрд╛рд░реНрдереНрдпрд╛рд╕рд╣ рдПрдХ ЁЯУг webhook received рдУрд│ рдЫрд╛рдкрддреЛ; рддреБрдореНрд╣реА рддреЛ рдмрдВрдж рдХреЗрд▓реНрдпрд╛рд╡рд░рд╣реА рдкреБрдврдЪрд╛ рдкреНрд░рд╡реЗрд╢ 201 рдЪ рджреЗрддреЛ рдЖрдгрд┐ server рдЪреНрдпрд╛ log рдордзреНрдпреЗ webhook тАж failed рджрд┐рд╕рддреЗ тАФ рдЕрдкрдпрд╢реА callback рдореБрд│реЗ рдХрд╛рдЙрдВрдЯрд░ рдХрдзреАрдЪ рдмрд┐рдШрдбрдд рдирд╛рд╣реА.

ЁЯПБ рддреБрдореНрд╣реА рдЖрддреНрддрд╛рдЪ рдХрд╛рдп рд╕рд┐рджреНрдз рдХреЗрд▓реЗ

рдХрд╛рдЙрдВрдЯрд░ рддреБрдореНрд╣рд╛рд▓рд╛ рдкрд░рдд рдХреЙрд▓ рдХрд░реВ рд╢рдХрддреЛ, рдЖрдгрд┐ webhooks рдЪреЗ рджреЛрди рдирд┐рдпрдо рддреБрдореНрд╣реА рджреЛрдиреНрд╣реА рдмрд╛рдЬреВрдВрдиреА рдкрд╛рд╣рд┐рд▓реЗ: producer рдХрдзреАрдЪ consumer рд╕рд╛рдареА рдЕрдбрдХреВрди рд░рд╛рд╣рдд рдирд╛рд╣реА, рдЖрдгрд┐ consumer рдиреЗ retries рдЪреА рдЕрдкреЗрдХреНрд╖рд╛ рдареЗрд╡рд▓реАрдЪ рдкрд╛рд╣рд┐рдЬреЗ.

тЪая╕П рдиреЗрд╣рдореАрдЪреНрдпрд╛ рдЪреБрдХрд╛

ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд рд╣реЗ рдХрд╛ рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ: payments, CI systems рдЖрдгрд┐ chat platforms рд╕рдЧрд│реЗ рдирд┐рдХрд╛рд▓ webhook рдиреЗ рдкреЛрд╣реЛрдЪрд╡рддрд╛рдд; рдЕрдВрддрд░реНрдЧрдд microservices gRPC рдмреЛрд▓рддрд╛рдд; screens endpoints рдкреЗрдХреНрд╖рд╛ рдореЛрдареЗ рдЭрд╛рд▓реЗ рдХреА product UIs GraphQL рд╕реНрд╡реАрдХрд╛рд░рддрд╛рдд. рднрд╛рдЧреАрджрд╛рд░ рдХреЛрдгрддрд╛ рдЖрдХрд╛рд░ рд╡рд╛рдкрд░рддреЛ тАФ рдЖрдгрд┐ рдХрд╛ тАФ рд╣реЗ рдУрд│рдЦрдгреЗ рд╣реЗ рд░реЛрдЬрдЪреЗ рдХреМрд╢рд▓реНрдп рдЖрд╣реЗ.

тПня╕П рдкреБрдвреЗ

рд╢реЗрд╡рдЯрдЪрд╛ рдЯрдкреНрдкрд╛: contract tests, рдХреЕрдЯрд▓реЙрдЧрдордзреВрди docs, рдЖрдгрд┐ рд╢рд╛рд│реЗрдЪреЗ рдЧреЗрдЯ (API gateway) рдкреНрд░рддреНрдпреЗрдХ рдХрд╛рдЙрдВрдЯрд░рд╕рдореЛрд░.

git checkout lesson-12-testing-docs-gateway

ЁЯФА Lesson 11 тАФ Beyond REST: when the counter calls you back

ЁЯУН You are here: Lesson 11 of 12 ┬╖ Previous: lesson-10-rate-limits-caching ┬╖ Next: lesson-12-testing-docs-gateway


ЁЯУж What's in this branch

Lessons 01тАУ10, plus the other shapes a counter can take тАФ GraphQL, gRPC, webhooks, events тАФ and the rule for picking one. Real files:

ЁЯФА The full map: this lesson teaches the four shapes you meet most. Every other type тАФ SOAP, tRPC, OData, WebRTC, queues, event streams, batch files, and the APIs that never touch a network (libraries, system calls, database drivers) тАФ is lesson 15 тАФ every API type: one master table, four families, and a decision guide.

ЁЯзТ Explain like I'm 5

REST is one kind of counter: named drawers, standard slips. Three other kinds exist, each for a real reason:

Picking is not fashion: the shape follows the caller.

ЁЯЧ║я╕П Diagram

flowchart LR
    rest["ЁЯЧДя╕П REST<br/>nouns + verbs, cacheable тАФ public, simple"]
    gql["ЁЯзй GraphQL<br/>ask for exactly these fields тАФ one UI, many shapes"]
    grpc["тЪб gRPC<br/>typed, binary, streaming тАФ service тЖФ service"]
    hook["ЁЯУг webhooks<br/>the counter calls you back on events"]
    ev["ЁЯУм events / queues<br/>'tell me when', replayable"]
    caller["ЁЯзн the shape follows the caller"] --> rest & gql & grpc & hook & ev

тЭУ What

ЁЯдФ Why

Because teams pick shapes by fashion and pay for years: a GraphQL API for a two-endpoint service, gRPC for a public API browsers must call, polling where a webhook was one registration away. Know the four shapes and the one rule, and the choice is usually obvious.

ЁЯФз How (in this repo)

POST /v1/webhooks {"url": тАж} registers a URL; notify() in school_api.py POSTs a student.created event to every registered URL after a successful enrolment тАФ and swallows failures, because a dead webhook must never break the counter. api/webhook_receiver.py is the other side: a 15-line server that prints what arrives.

ЁЯзк Try it

# A) six shapes, one dataset тАФ REST ┬╖ JSON-RPC ┬╖ GraphQL ┬╖ long polling ┬╖ SSE ┬╖ WebSocket
python3 api/api_types.py &                                           # :8081
python3 api/types_client.py                                          # every byte of all six, printed
# read the differences: whole resource vs chosen fields vs an error inside a 200 vs a held request vs a stream vs a socket

# B) the webhook, from both sides:
python3 api/webhook_receiver.py &                                    # terminal 3: your phone rings here on :9090
B=http://127.0.0.1:8080/v1; K='X-API-Key: hall-pass-123'; J='Content-Type: application/json'
curl -s -X POST $B/webhooks -H "$J" -d '{"url":"http://127.0.0.1:9090/hook"}'
curl -s -X POST $B/students -H "$K" -H "$J" -d '{"name":"Zoya","class":"3B"}' > /dev/null
# terminal 3 prints: ЁЯУг webhook received: {'event': 'student.created', 'student': {...}}
kill %1                                                              # now the receiver is dead тАФ
curl -s -X POST $B/students -H "$K" -H "$J" -d '{"name":"Yash","class":"3A"}' | head -c 80   # still 201: the counter survives

тЬЕ Verify тАФ what you should see

types_client.py prints six labelled sections and ends with тЬЕ six shapes, one dataset: REST returns whole resources, JSON-RPC returns error inside a 200, GraphQL returns only the fields you named, long polling answers ~0.4 s late with one event, SSE prints id:/event:/data: frames (and replays history when you send Last-Event-ID: 0), and the WebSocket shows 101 Switching Protocols before echoing both ways.

The receiver prints one ЁЯУг webhook received line with the new student; after you kill it, the next enrolment still returns 201 and the server's log shows webhook тАж failed тАФ a failing callback never breaks the counter.

ЁЯПБ What you just proved

The counter can call you back, and you saw the two rules of webhooks from both sides: the producer never blocks on the consumer, and the consumer must expect retries.

тЪая╕П Common mistakes

ЁЯПн Why this matters in production: payments, CI systems and chat platforms all deliver results by webhook; internal microservices talk gRPC; product UIs adopt GraphQL when screens outgrow endpoints. Recognising which shape a partner uses тАФ and why тАФ is a daily skill.

тПня╕П Next

The last mile: contract tests, docs from the catalogue, and the school gate (API gateway) in front of every counter.

git checkout lesson-12-testing-docs-gateway
тЖР Previousrate limits cachingNext тЖТtesting docs gateway

This page is the lesson's README from the lesson-11-beyond-rest branch, shown here so the whole School stays on one site. Code files open on GitHub at the same branch.