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

ЁЯз░ рдзрдбрд╛ 02 тАФ REST рд╡рд┐рд░реБрджреНрдз HTTP рд╡рд┐рд░реБрджреНрдз WebSocket APIs: front office рдЪреЗ рддреАрди рдкреНрд░рдХрд╛рд░

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


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

рдзрдбрд╛ 01, рдЖрдгрд┐ AWS рд╡рд░ рддреБрдореНрд╣реА рд╕рд░реНрд╡рд╛рдд рдЖрдзреА рдХрд░рддрд╛ рддреА рдирд┐рд╡рдб: REST API (рдкреВрд░реНрдг рд╕рд╛рд╣рд┐рддреНрдп), HTTP API (рд╣рд▓рдХреЗ рдЖрдгрд┐ рд╕реНрд╡рд╕реНрдд) рдХрд┐рдВрд╡рд╛ WebSocket API (рдЙрдШрдбреА рд░рд╛рд╣рдгрд╛рд░реА line). apigw/demo.py рдордзрд▓реЗ kinds() рд╣реЗ рддрд┐рдиреНрд╣реА print рдХрд░рддреЗ, рдЖрдгрд┐ lab рдЪреЗ office рдХреЛрдгрддреЗ рдлрдХреНрдд-REST рднрд╛рдЧ рд╡рд╛рдкрд░рддреЗ рддреНрдпрд╛рдВрдЪреА рддреБрдореНрд╣реА рдпрд╛рджреА рдХрд░рддрд╛.

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

рд╢рд╛рд│рд╛ рддрд┐рдЪреЗ front office рддреАрди рдкреНрд░рдХрд╛рд░реЗ рдмрд╛рдВрдзреВ рд╢рдХрддреЗ:

  1. рдкреВрд░реНрдг office ЁЯПв (REST API). рдореЛрдард╛ desk, рдЕрдиреЗрдХ рдЦрдг: рд░реЛрдЬрдЪреНрдпрд╛ рдорд░реНрдпрд╛рджреЗрд╕рд╣ visitor passes (API keys рдЖрдгрд┐ usage plans), рд╕реВрдЪрдирд╛ рдлрд▓рдХ (cache), form рддрдкрд╛рд╕рдгрд╛рд░рд╛ (request validation), рдкрддреНрд░реЗ рдирд╡реНрдпрд╛рдиреЗ рд▓рд┐рд╣рд┐рдгрд╛рд░рд╛ clerk (mapping templates), рдлрд╛рдЯрдХрд╛рд╡рд░рдЪрд╛ рдкрд╣рд╛рд░реЗрдХрд░реА (AWS WAF), рдЖрдгрд┐ рдлрдХреНрдд рдЖрддрд▓реНрдпрд╛ visitors рд╕рд╛рдареА рдПрдХ рдЦрд╛рдЬрдЧреА рджрд╛рд░.
  2. рдЬрд▓рдж counter ЁЯкЯ (HTTP API). рд▓рд╣рд╛рди рдЖрдгрд┐ рд╕реНрд╡рд╕реНрдд. рддреЗ badges рддрдкрд╛рд╕рддреЗ (JWT), рдПрдХрд╛ setting рдиреЗ browsers рдирд╛ рдЖрдд рдпреЗрдК рджреЗрддреЗ (CORS) рдЖрдгрд┐ рдкрдЯрдХрди рдкреБрдвреЗ рдкрд╛рдард╡рддреЗ. рд╕реВрдЪрдирд╛ рдлрд▓рдХ рдирд╛рд╣реА, visitor passes рдирд╛рд╣реАрдд.
  3. Phone line тШОя╕П (WebSocket API). Visitor рдПрдХрджрд╛ call рдХрд░рддреЛ рдЖрдгрд┐ line рдЙрдШрдбреАрдЪ рд░рд╛рд╣рддреЗ. рджреЛрдиреНрд╣реА рдмрд╛рдЬреВ рдХрдзреАрд╣реА рдмреЛрд▓реВ рд╢рдХрддрд╛рдд тАФ marks рддрдпрд╛рд░ рдЭрд╛рд▓реЗ рдХреА рд╢рд╛рд│рд╛ рдкрд░рдд call рдХрд░реВ рд╢рдХрддреЗ.

рддреБрдореНрд╣рд╛рд▓рд╛ рд▓рд╛рдЧрдгрд╛рд░реЗ рд╕рдЧрд│реЗ рдЦрдг рдЬреНрдпрд╛рдд рдЖрд╣реЗрдд рдЕрд╕реЗ рд╕рд░реНрд╡рд╛рдд рд▓рд╣рд╛рди office рдирд┐рд╡рдбрд╛.

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

flowchart TB
    q["тЭУ what do you need?"]
    rest["ЁЯПв REST API<br/>keys + usage plans ┬╖ cache ┬╖ validation<br/>VTL mapping ┬╖ WAF ┬╖ private endpoint<br/>~$3.50 per million"]
    http["ЁЯкЯ HTTP API<br/>JWT authorizer ┬╖ simple CORS<br/>auto-deploy ┬╖ Lambda + HTTP proxy<br/>~$1.00 per million"]
    ws["тШОя╕П WebSocket API<br/>$connect ┬╖ $disconnect ┬╖ $default<br/>route by a field in the message"]
    q -->|"partners, quotas, caching, WAF"| rest
    q -->|"JWT + Lambda, lower price"| http
    q -->|"server must push: chat, live marks"| ws

ЁЯЧ║я╕П рдХрд╛рдврд▓реЗрд▓реА рдЖрд╡реГрддреНрддреА + рдПрдХ lab: https://school-edh.pages.dev/apigateway/lesson-diagrams.html#l02

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

ЁЯдФ рдХрд╛

рдХрд╛рд░рдг рд╣реА рдирд┐рд╡рдб рддреБрдордЪреА рдХрд┐рдВрдордд рдард░рд╡рддреЗ, рдЖрдгрд┐ рдХреЛрдгрддреА features рддреБрдореНрд╣реА рдХрдзреАрд╣реА рдЪрд╛рд▓реВ рдХрд░реВ рд╢рдХрд╛рд▓ рддреЗрд╣реА. Teams рдЕрдиреЗрдХрджрд╛ "рд╕реБрд░рдХреНрд╖рд┐рдд рд░рд╛рд╣рд╛рд╡реЗ" рдореНрд╣рдгреВрди REST рдирд┐рд╡рдбрддрд╛рдд рдЖрдгрд┐ рдХрдзреАрдЪ рди рд╡рд╛рдкрд░рд▓реЗрд▓реНрдпрд╛ features рд╕рд╛рдареА рдЬрд╡рд│рдкрд╛рд╕ рд╕рд╛рдбреЗрддреАрди рдкрдЯ рдЬрд╛рд╕реНрдд рдкреИрд╕реЗ рджреЗрддрд╛рдд. рдЗрддрд░ HTTP рдирд┐рд╡рдбрддрд╛рдд рдЖрдгрд┐ рдирдВрддрд░ рддреНрдпрд╛рдВрдирд╛ рдХрд│рддреЗ рдХреА partners рд╕рд╛рдареА usage plans рдХрд┐рдВрд╡рд╛ рд╕рдореЛрд░ WAF рд╣рд╡рд╛ рдЖрд╣реЗ тАФ рдЖрдгрд┐ рдордЧ migrate рдХрд░рд╛рд╡реЗ рд▓рд╛рдЧрддреЗ. рдирд╛рд╡рд╛рд╡рд░реВрди рдирд╛рд╣реА, рддрд░ features рдЪреНрдпрд╛ рдпрд╛рджреАрд╡рд░реВрди рдирд┐рд░реНрдгрдп рдШреНрдпрд╛.

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

kinds() рддрд┐рдиреНрд╣реА рдкреНрд░рдХрд╛рд░ print рдХрд░рддреЗ. office() REST-рдкрджреНрдзрддреАрдЪрд╛ API рдмрдирд╡рддреЗ, рдЖрдгрд┐ apigw/gateway.py рдордзрд▓рд╛ рдкреНрд░рддреНрдпреЗрдХ Route REST features flags рдореНрд╣рдгреВрди рдмрд╛рд│рдЧрддреЛ: auth, cache, api_key, schema (request validation) рдЖрдгрд┐ mapping (response mapping). Routes рдЪреА рдпрд╛рджреА рдХреЗрд▓реА рдХреА lab рдкреВрд░реНрдг office рдЪреЗ рдХреЛрдгрддреЗ рдЦрдг рд╡рд╛рдкрд░рддреЗ рддреЗ рджрд┐рд╕рддреЗ.

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

python3 apigw/demo.py kinds
python3 - <<'EOF'
import sys; sys.path.insert(0, "apigw"); from demo import office
gw, _ = office()
for r in gw.routes:
    print(f"{r.method:<5} {r.path:<24} auth={r.auth} cache={r.cache} api_key={r.api_key} schema={'yes' if r.schema else 'no'} mapping={'yes' if r.mapping else 'no'}")
print("stages:", list(gw.stages), "┬╖ usage plans:", list(gw.plans))
EOF

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

kinds рддреАрди рдУрд│реА print рдХрд░рддреЗ: REST API the full kit: API keys + usage plans, caching, request validation, mapping templates, WAF, private, HTTP API lean and cheaper: JWT authorizers built in, CORS in one setting, Lambda + HTTP proxy, WebSocket API a phone line that stays open: $connect, $disconnect, routes by a field in the message, рдордЧ this lab models a REST API because it shows the most parts.

рддреБрдордЪрд╛ snippet рдЖрда routes print рдХрд░рддреЛ. рддреНрдпрд╛рдкреИрдХреА рддреАрди рдлрдХреНрдд-REST рдЦрдг рд╡рд╛рдкрд░рддрд╛рдд: GET /students/{id} auth=None cache=True api_key=False schema=no mapping=yes (cache рдЖрдгрд┐ mapping), POST /marks auth=jwt cache=False api_key=False schema=yes mapping=no (validation) рдЖрдгрд┐ GET /partner/students/{id} auth=None cache=False api_key=True schema=no mapping=no (API key). рдордЧ stages: ['dev', 'prod'] ┬╖ usage plans: ['partner-basic']. HTTP API рдордзреНрдпреЗ cache, validator, mapping рдХрд┐рдВрд╡рд╛ usage plan рдмрд╕реВ рд╢рдХрд▓реЗ рдирд╕рддреЗ.

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

API рдЪреНрдпрд╛ рдЧрд░рдЬрд╛ рд╡рд╛рдЪреВрди рддреБрдореНрд╣реА рддреНрдпрд╛рдЪрд╛ рдкреНрд░рдХрд╛рд░ рд╕рд╛рдВрдЧреВ рд╢рдХрддрд╛: рд╣рд╛ рд╢рд╛рд│реЗрдЪрд╛ API cache, validator, mapping рдЖрдгрд┐ usage plan рд╡рд╛рдкрд░рддреЛ, рдореНрд╣рдгреВрди рддреНрдпрд╛рд▓рд╛ REST API рд▓рд╛рдЧрддреЛ. рддреНрдпрд╛ рдЪрд╛рд░ рдЧреЛрд╖реНрдЯреА рдирд╕рддреНрдпрд╛, рддрд░ HTTP API рдиреЗ рддреЗрдЪ рдХрд╛рдо рдХрдореА рдЦрд░реНрдЪрд╛рдд рдХреЗрд▓реЗ рдЕрд╕рддреЗ.

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

ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд

On a real account тАФ рддреЛрдЪ students route HTTP API (AWS SAM) рдореНрд╣рдгреВрди рдЖрдгрд┐ REST API (AWS SAM) рдореНрд╣рдгреВрди, рд╢реЗрдЬрд╛рд░реА рд╢реЗрдЬрд╛рд░реА:

# template.yaml тАФ AWS SAM
Resources:
  StudentsFn:
    Type: AWS::Serverless::Function
    Properties:
      Runtime: python3.12
      Handler: app.handler
      CodeUri: src/
      Events:
        LeanCounter:                       # HTTP API
          Type: HttpApi
          Properties: { Path: /students/{id}, Method: GET }
        FullOffice:                        # REST API
          Type: Api
          Properties: { Path: /students/{id}, Method: GET }

WebSocket API рддреНрдпрд╛рдЪрд╛ route message body рд╡рд░реВрди рдирд┐рд╡рдбрддреЛ:

aws apigatewayv2 create-api --name school-live --protocol-type WEBSOCKET \
    --route-selection-expression '$request.body.action'

ЁЯПн Production рдордзреНрдпреЗ рд╣реЗ рдХрд╛ рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ: рдкреНрд░рдХрд╛рд░ рдирдВрддрд░ рдмрджрд▓рдгреЗ рдЕрд╡рдШрдб рдЕрд╕рддреЗ тАФ clients, domains рдЖрдгрд┐ authorizers рддреНрдпрд╛рдЪреНрдпрд╛рднреЛрд╡рддреА рдмрд╛рдВрдзрд▓реЗрд▓реЗ рдЕрд╕рддрд╛рдд. API рдмрдирд╡рдгреНрдпрд╛рдЖрдзреА рддреБрдореНрд╣рд╛рд▓рд╛ рд▓рд╛рдЧрдгрд╛рд░реА features рд▓рд┐рд╣реВрди рдареЗрд╡рд╛ (keys? cache? WAF? private?).

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

Office рдирд┐рд╡рдбрд▓реЗ. рдЖрддрд╛: рдХреЛрдгрддрд╛ desk рдХреЛрдгрддреНрдпрд╛ visitor рд▓рд╛ рдШреЗрддреЛ? Routes рдЖрдгрд┐ integrations.

git checkout lesson-03-routes-integrations

ЁЯз░ Lesson 02 тАФ REST vs HTTP vs WebSocket APIs: three kinds of front office

ЁЯУН You are here: Lesson 02 of 12 ┬╖ Previous: lesson-01-why-gateway ┬╖ Next: lesson-03-routes-integrations


ЁЯУж What's in this branch

Lesson 01, plus the choice you make first on AWS: a REST API (the full kit), an HTTP API (lean and cheaper) or a WebSocket API (a line that stays open). kinds() in apigw/demo.py prints the three, and you list which REST-only parts the lab office uses.

ЁЯзТ Explain like I'm 5

The school can build its front office in three ways:

  1. The full office ЁЯПв (REST API). Big desk, many drawers: visitor passes with daily limits (API keys and usage plans), a notice board (cache), a form checker (request validation), a clerk who rewrites letters (mapping templates), a guard at the gate (AWS WAF), and a private door for inside visitors only.
  2. The quick counter ЁЯкЯ (HTTP API). Smaller and cheaper. It checks badges (JWT), lets browsers in with one setting (CORS) and forwards fast. No notice board, no visitor passes.
  3. The phone line тШОя╕П (WebSocket API). The visitor calls once and the line stays open. Both sides can talk at any time тАФ the school can call back when the marks are ready.

Pick the smallest office that has every drawer you need.

ЁЯЧ║я╕П Diagram

flowchart TB
    q["тЭУ what do you need?"]
    rest["ЁЯПв REST API<br/>keys + usage plans ┬╖ cache ┬╖ validation<br/>VTL mapping ┬╖ WAF ┬╖ private endpoint<br/>~$3.50 per million"]
    http["ЁЯкЯ HTTP API<br/>JWT authorizer ┬╖ simple CORS<br/>auto-deploy ┬╖ Lambda + HTTP proxy<br/>~$1.00 per million"]
    ws["тШОя╕П WebSocket API<br/>$connect ┬╖ $disconnect ┬╖ $default<br/>route by a field in the message"]
    q -->|"partners, quotas, caching, WAF"| rest
    q -->|"JWT + Lambda, lower price"| http
    q -->|"server must push: chat, live marks"| ws

ЁЯЧ║я╕П Drawn version + a lab: https://school-edh.pages.dev/apigateway/lesson-diagrams.html#l02

тЭУ What

ЁЯдФ Why

Because the choice decides your price and which features you can ever turn on. Teams often pick REST "to be safe" and pay about three and a half times more for features they never use. Others pick HTTP and later find they need usage plans for partners or WAF in front тАФ and must migrate. Decide from the feature list, not from the name.

ЁЯФз How (in this repo)

kinds() prints the three kinds. office() builds a REST-style API, and each Route in apigw/gateway.py carries the REST features as flags: auth, cache, api_key, schema (request validation) and mapping (response mapping). Listing the routes shows which drawers of the full office the lab uses.

ЁЯзк Try it

python3 apigw/demo.py kinds
python3 - <<'EOF'
import sys; sys.path.insert(0, "apigw"); from demo import office
gw, _ = office()
for r in gw.routes:
    print(f"{r.method:<5} {r.path:<24} auth={r.auth} cache={r.cache} api_key={r.api_key} schema={'yes' if r.schema else 'no'} mapping={'yes' if r.mapping else 'no'}")
print("stages:", list(gw.stages), "┬╖ usage plans:", list(gw.plans))
EOF

тЬЕ Verify тАФ what you should see

kinds prints three lines: REST API the full kit: API keys + usage plans, caching, request validation, mapping templates, WAF, private, HTTP API lean and cheaper: JWT authorizers built in, CORS in one setting, Lambda + HTTP proxy, WebSocket API a phone line that stays open: $connect, $disconnect, routes by a field in the message, then this lab models a REST API because it shows the most parts.

Your snippet prints eight routes. Three of them use REST-only drawers: GET /students/{id} auth=None cache=True api_key=False schema=no mapping=yes (cache and mapping), POST /marks auth=jwt cache=False api_key=False schema=yes mapping=no (validation) and GET /partner/students/{id} auth=None cache=False api_key=True schema=no mapping=no (API key). Then stages: ['dev', 'prod'] ┬╖ usage plans: ['partner-basic']. An HTTP API could not hold the cache, the validator, the mapping or the usage plan.

ЁЯПБ What you just proved

You can read an API's needs and name the kind: this school API uses a cache, a validator, a mapping and a usage plan, so it needs a REST API. Without those four, an HTTP API would do the same job for less.

тЪая╕П Common mistakes

ЁЯПн In production

On a real account тАФ the same students route as an HTTP API (AWS SAM) and as a REST API (AWS SAM), side by side:

# template.yaml тАФ AWS SAM
Resources:
  StudentsFn:
    Type: AWS::Serverless::Function
    Properties:
      Runtime: python3.12
      Handler: app.handler
      CodeUri: src/
      Events:
        LeanCounter:                       # HTTP API
          Type: HttpApi
          Properties: { Path: /students/{id}, Method: GET }
        FullOffice:                        # REST API
          Type: Api
          Properties: { Path: /students/{id}, Method: GET }

A WebSocket API picks its route from the message body:

aws apigatewayv2 create-api --name school-live --protocol-type WEBSOCKET \
    --route-selection-expression '$request.body.action'

ЁЯПн Why this matters in production: the kind is hard to change later тАФ clients, domains and authorizers are built around it. Write down the features you need (keys? cache? WAF? private?) before you create the API.

тПня╕П Next

The office is chosen. Now: which desk takes which visitor? Routes and integrations.

git checkout lesson-03-routes-integrations
тЖР Previouswhy gatewayNext тЖТroutes integrations

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