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

ЁЯУи рдзрдбрд╛ 02 тАФ HTTP рдЪреА рд░рдЪрдирд╛: рдЪрд┐рдареНрдареА рдЖрдгрд┐ рд╢рд┐рдХреНрдХрд╛

ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 12 рдкреИрдХреА рдзрдбрд╛ 02 ┬╖ рдорд╛рдЧреЗ: lesson-01-why-apis ┬╖ рдкреБрдвреЗ: lesson-03-rest-resources


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

рдзрдбрд╛ 01, рдЖрдгрд┐ рддреНрдпрд╛рд╕реЛрдмрдд request рдЖрдгрд┐ response рдЪреА рдиреЗрдордХреА рд░рдЪрдирд╛ тАФ рдкреНрд░рддреНрдпреЗрдХ slip рд╡рд░рдЪреНрдпрд╛ рдкрд╛рдЪ рдЧреЛрд╖реНрдЯреА рдЖрдгрд┐ рдкреНрд░рддреНрдпреЗрдХ рд╢рд┐рдХреНрдХрд╛ рдорд╛рд░рд▓реЗрд▓реНрдпрд╛ рдЙрддреНрддрд░рд╛рд╡рд░рдЪреНрдпрд╛ рддреАрди рдЧреЛрд╖реНрдЯреА.

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

Counter рд╡рд░рдЪреНрдпрд╛ рдкреНрд░рддреНрдпреЗрдХ slip рд╡рд░ рддреЗрдЪ рд░рдХрд╛рдиреЗ рдЕрд╕рддрд╛рдд, рдиреЗрд╣рдореА рддреНрдпрд╛рдЪ рдХреНрд░рдорд╛рдиреЗ:

  1. рдХрд╛рдп рдХрд░рд╛рдпрдЪреЗ тАФ method: GET (рд╡рд╛рдЪрд╛), POST (рдЬреЛрдбрд╛), PUT (рдкреВрд░реНрдг рдмрджрд▓рд╛), DELETE (рдХрд╛рдврд╛).
  2. рдХрд╢рд╛рдмрджреНрджрд▓ тАФ path: /v1/students/2.
  3. рд╕рдорд╛рд╕рд╛рддрд▓реНрдпрд╛ рдЬрд╛рджрд╛ рдиреЛрдВрджреА тАФ headers: "рдорд▓рд╛ JSON рд╕рдордЬрддреЗ" (Accept), "рд╣рд╛ рдорд╛рдЭрд╛ pass" (X-API-Key), "рдмрджрд▓рд▓реЗ рдЕрд╕реЗрд▓ рддрд░рдЪ" (If-None-Match).
  4. рдкреНрд░рддреНрдпрдХреНрд╖ form тАФ body: рдлрдХреНрдд рддреБрдореНрд╣реА рдХрд╛рд╣реА рдЬреЛрдбрдд рдХрд┐рдВрд╡рд╛ рдмрджрд▓рдд рдЕрд╕рд╛рд▓ рддреЗрд╡реНрд╣рд╛ ({"name": "Zoya", "class": "3B"}).
  5. рд╢реЗрд╡рдЯреА рдПрдХ query тАФ ?limit=2&class=3A: filters рдЖрдгрд┐ рдкрд░реНрдпрд╛рдп.

Clerk рдЪреНрдпрд╛ рдЙрддреНрддрд░рд╛рдЪреЗ рддреАрди рднрд╛рдЧ рдЕрд╕рддрд╛рдд: рд╢рд┐рдХреНрдХрд╛ (status code), рдХрд╛рд╣реА рд╕рдорд╛рд╕рд╛рддрд▓реНрдпрд╛ рдиреЛрдВрджреА (ETag, Content-Type, Location рд╕рд╛рд░рдЦреЗ headers), рдЖрдгрд┐ рдордЬрдХреВрд░ (body, рдмрд╣реБрддреЗрдХ рд╡реЗрд│рд╛ JSON). рд╢рд┐рдХреНрдХреЗ рдХреБрдЯреБрдВрдмрд╛рдВрдд рдпреЗрддрд╛рдд:

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

sequenceDiagram
    participant C as ЁЯзС client
    participant S as ЁЯПв school-api
    C->>S: 1 GET /v1/students/2  (Accept: application/json)
    S-->>C: 2 200 OK ┬╖ ETag "0e9aтАж" ┬╖ Cache-Control ┬╖ {"id":2,"name":"Katrina",тАж}
    C->>S: 3 GET /v1/students/99
    S-->>C: 4 404 Not Found ┬╖ {"error":{"code":"not_found","message":"No student with id 99."}}
    Note over C,S: 2xx done ┬╖ 3xx elsewhere ┬╖ 4xx your slip ┬╖ 5xx our office

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

ЁЯФз рд╕рд╛рддрд╣реА рд╢рд┐рдХреНрдХреЗ, рдЪрд┐рддреНрд░рд╛рдд: GET, HEAD, OPTIONS, POST, PUT, PATCH рдЖрдгрд┐ DELETE тАФ safe, idempotent, cacheable, рдкреНрд░рддреНрдпреЗрдХ рджреЗрдд рдЕрд╕рд▓реЗрд▓реЗ status codes, рдЖрдгрд┐ рдкреНрд░рддреНрдпреЗрдХ рдирд┐рдпрдо рдпрд╛ counter рд╡рд░ рд╕рд┐рджреНрдз рдХрд░рдгрд╛рд░реА script тАФ рд╣реЗ рд╕рдЧрд│реЗ рдзрдбрд╛ 13 тАФ рдкреНрд░рддреНрдпреЗрдХ REST method рдордзреНрдпреЗ рдЖрд╣реЗ. bash api/methods_demo.sh рддреЗ рдЪрд╛рд▓рд╡рддреЗ (HEAD рдЖрдгрд┐ OPTIONS рд╕реБрджреНрдзрд╛ рдЙрддреНрддрд░ рджреЗрддрд╛рдд: curl -I рдЖрдгрд┐ curl -X OPTIONS -i рдХрд░реВрди рдкрд╛рд╣рд╛).

ЁЯдФ рдХрд╛

рдХрд╛рд░рдг рдпрд╛ рдХреНрд╖реЗрддреНрд░рд╛рддрд▓реЗ рдкреНрд░рддреНрдпреЗрдХ рд╕рд╛рдзрди тАФ curl, browsers, load balancers, caches, AWS API Gateway, рддреБрдордЪрд╛ framework тАФ рд╣реАрдЪ рдиреЗрдордХреА рд░рдЪрдирд╛ рд╕рдордЬрддреЗ. рддреА рдЕрд╕реНрдЦрд▓рд┐рдд рдмреЛрд▓рддрд╛ рдЖрд▓реА рдХреА рддреБрдореНрд╣реА curl -v рдиреЗ рдЖрдгрд┐ docs рд╢рд┐рд╡рд╛рдп рдХреЛрдгрддреЗрд╣реА API debug рдХрд░реВ рд╢рдХрддрд╛: method рдЖрдгрд┐ path рд╕рд╛рдВрдЧрддрд╛рдд рддреБрдореНрд╣реА рдХрд╛рдп рдорд╛рдЧрд┐рддрд▓реЗ, status рд╕рд╛рдВрдЧрддреЛ рдЪреВрдХ рдХреЛрдгрд╛рдЪреА рдЖрд╣реЗ, headers рд╕рд╛рдВрдЧрддрд╛рдд рдкреБрдвреЗ рдХрд╛рдп рдХрд░рд╛рдпрдЪреЗ.

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

school_api.py рдордзрд▓реЗ send(status, body, headers) рдкреНрд░рддреНрдпреЗрдХ рд╢рд┐рдХреНрдХрд╛ рд▓рд┐рд╣рд┐рддреЗ: status line, X-API-Version, X-Request-Id, Content-Type, body. error(status, code, message) рдкреНрд░рддреНрдпреЗрдХ рдирдХрд╛рд░ рдПрдХрд╛рдЪ рдЖрдХрд╛рд░рд╛рдд рд▓рд┐рд╣рд┐рддреЗ тАФ рд╣реЗ рдЗрддрдХреЗ рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ рдХрд╛ рдЖрд╣реЗ рддреЗ рдзрдбрд╛ 07 рд╕рд╛рдВрдЧрддреЛ.

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

python3 api/school_api.py                          # terminal 1
curl -v http://127.0.0.1:8080/v1/students/2        # terminal 2 тАФ read the > and < lines
curl -i http://127.0.0.1:8080/v1/students/99       # the 404 stamp + the error body
curl -i -X POST http://127.0.0.1:8080/v1/students -d 'not json'   # 415: wrong paper

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

curl -v рддреБрдордЪреНрдпрд╛ request рдЪреНрдпрд╛ рдУрд│реА > рдиреЗ рд╕реБрд░реВ рдЭрд╛рд▓реЗрд▓реНрдпрд╛ (method, path, Host, Accept) рдЖрдгрд┐ рдЙрддреНрддрд░ < рдиреЗ рд╕реБрд░реВ рдЭрд╛рд▓реЗрд▓реЗ (HTTP/1.0 200 OK, ETag, Cache-Control, Content-Type) рджрд╛рдЦрд╡рддреЛ. 404 рд▓рд╛ error.code = not_found рдЕрд╕рд▓реЗрд▓реА JSON body рдЕрд╕рддреЗ. -d 'not json' call auth рддрдкрд╛рд╕рдгреНрдпрд╛рдЪреНрдпрд╛ рдЖрдзреАрдЪ 415 unsupported_media_type рдиреЗ рдирд╛рдХрд╛рд░рд▓рд╛ рдЬрд╛рддреЛ.

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

рддреБрдореНрд╣реА request рдЖрдгрд┐ response text рдореНрд╣рдгреВрди рд╡рд╛рдЪреВ рд╢рдХрддрд╛, рдЖрдгрд┐ рдкреНрд░рддреНрдпреЗрдХ рдЙрддреНрддрд░ рдЪрд╛рд░ рд╢рд┐рдХреНрдХрд╛-рдХреБрдЯреБрдВрдмрд╛рдВрдкреИрдХреА рдХреЛрдгрддреНрдпрд╛ рдХреБрдЯреБрдВрдмрд╛рддрд▓реЗ рдЖрд╣реЗ рддреЗ рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд│рддреЗ тАФ API debugging рдЪрд╛ 80 % рднрд╛рдЧ рд╣рд╛рдЪ рдЖрд╣реЗ.

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

ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд рд╣реЗ рдХрд╛ рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ: load balancers 5xx рдореЛрдЬрддрд╛рдд, caches Cache-Control рдкрд╛рд│рддрд╛рдд, alerting рдкреНрд░рддреНрдпреЗрдХ status рдХреБрдЯреБрдВрдмрд╛рдЪреНрдпрд╛ error рджрд░рд╛рд╡рд░ рд╡рд╛рдЬрддреЗ. рдЖрдд {"ok": false} рдареЗрд╡реВрди 200 рдкрд░рдд рдХрд░рдгрд╛рд░реЗ API рдпрд╛ рдкреНрд░рддреНрдпреЗрдХ рд╕рд╛рдзрдирд╛рд▓рд╛ рджрд┐рд╕рддрдЪ рдирд╛рд╣реА.

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

Slips рд╡рд░рдЪреНрдпрд╛ рдЧреЛрд╖реНрдЯреАрдВрдирд╛ рдирд╛рд╡реЗ рдХрд╢реА рджреНрдпрд╛рдпрдЪреА? рдлрд╛рдЗрд▓рд┐рдВрдЧ рдХрдкрд╛рдЯрд╛рдВрддрд▓реА рдирд╛рдореЗ тАФ REST resources рдЖрдгрд┐ рдкреБрдиреНрд╣рд╛ рдХрд░рд╛рдпрд▓рд╛ рд╕реБрд░рдХреНрд╖рд┐рдд рдЕрд╕рд▓реЗрд▓реА рдХреНрд░рд┐рдпрд╛рдкрджреЗ.

git checkout lesson-03-rest-resources

ЁЯУи Lesson 02 тАФ HTTP anatomy: the slip and the stamp

ЁЯУН You are here: Lesson 02 of 12 ┬╖ Previous: lesson-01-why-apis ┬╖ Next: lesson-03-rest-resources


ЁЯУж What's in this branch

Lesson 01, plus the exact layout of a request and a response тАФ the five things on every slip and the three things on every stamped answer.

ЁЯзТ Explain like I'm 5

Every slip at the counter has the same boxes, always in the same order:

  1. What to do тАФ the method: GET (read), POST (add), PUT (replace), DELETE (remove).
  2. About what тАФ the path: /v1/students/2.
  3. Extra notes in the margin тАФ headers: "I speak JSON" (Accept), "here is my pass" (X-API-Key), "only if it changed" (If-None-Match).
  4. The form itself тАФ the body: only when you are adding or replacing something ({"name": "Zoya", "class": "3B"}).
  5. A query at the end тАФ ?limit=2&class=3A: filters and options.

The clerk's answer has three parts: the stamp (a status code), some margin notes (headers such as ETag, Content-Type, Location), and the contents (the body, usually JSON). Stamps come in families:

ЁЯЧ║я╕П Diagram

sequenceDiagram
    participant C as ЁЯзС client
    participant S as ЁЯПв school-api
    C->>S: 1 GET /v1/students/2  (Accept: application/json)
    S-->>C: 2 200 OK ┬╖ ETag "0e9aтАж" ┬╖ Cache-Control ┬╖ {"id":2,"name":"Katrina",тАж}
    C->>S: 3 GET /v1/students/99
    S-->>C: 4 404 Not Found ┬╖ {"error":{"code":"not_found","message":"No student with id 99."}}
    Note over C,S: 2xx done ┬╖ 3xx elsewhere ┬╖ 4xx your slip ┬╖ 5xx our office

тЭУ What

ЁЯФз All seven stamps, drawn: GET, HEAD, OPTIONS, POST, PUT, PATCH and DELETE тАФ safe, idempotent, cacheable, the status codes each returns, and a script that proves every rule against this counter тАФ are lesson 13 тАФ every REST method. bash api/methods_demo.sh runs it (HEAD and OPTIONS answer too: try curl -I and curl -X OPTIONS -i).

ЁЯдФ Why

Because every tool in the trade тАФ curl, browsers, load balancers, caches, the AWS API Gateway, your framework тАФ understands this exact layout. Speak it fluently and you can debug any API with curl -v and no docs: the method and path say what you asked, the status says whose fault it is, the headers say what to do next.

ЁЯФз How (in this repo)

send(status, body, headers) in school_api.py writes every stamp: the status line, X-API-Version, X-Request-Id, Content-Type, the body. error(status, code, message) writes every refusal in one shape тАФ lesson 07 explains why that matters so much.

ЁЯзк Try it

python3 api/school_api.py                          # terminal 1
curl -v http://127.0.0.1:8080/v1/students/2        # terminal 2 тАФ read the > and < lines
curl -i http://127.0.0.1:8080/v1/students/99       # the 404 stamp + the error body
curl -i -X POST http://127.0.0.1:8080/v1/students -d 'not json'   # 415: wrong paper

тЬЕ Verify тАФ what you should see

curl -v shows your request lines prefixed > (method, path, Host, Accept) and the answer prefixed < (HTTP/1.0 200 OK, ETag, Cache-Control, Content-Type). The 404 has a JSON body with error.code = not_found. The -d 'not json' call is refused with 415 unsupported_media_type before auth is even checked.

ЁЯПБ What you just proved

You can read a request and a response as text, and you know which of the four stamp families each answer belongs to тАФ that is 80 % of API debugging.

тЪая╕П Common mistakes

ЁЯПн Why this matters in production: load balancers count 5xx, caches obey Cache-Control, alerting fires on error rates per status family. An API that returns 200 with {"ok": false} inside is invisible to every one of those tools.

тПня╕П Next

How do we name the things on the slips? Nouns in filing cabinets тАФ REST resources and the verbs that are safe to repeat.

git checkout lesson-03-rest-resources
тЖР Previouswhy apisNext тЖТrest resources

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