0%

Talking to an API · practice

Check Status Before JSON

A JSON error envelope is still an unsuccessful HTTP response. Code that decodes first can accidentally treat {"error": ...} as ordinary catalog data.

Replace the temporary status read in request_json with the status boundary:

    response.raise_for_status()
    return response.json()

The order is the contract. A 200 reaches json(). /items/99, the deliberate /scenarios/not-found, and /scenarios/server-error raise HTTPError before their bodies can be mistaken for success.

Do not catch anything inside request_json. It cannot decide what a command should print or which exit status the caller needs. At a command boundary, the narrow pattern is:

try:
    document = request_json("/items/99")
except requests.HTTPError as exc:
    print(exc.response.status_code)

Read the status from exc.response.status_code, not from text. The capstone will turn that into one stable user-facing message. Unrelated programming defects must still escape with their .

Try both routes against the live internal service if you want to see the real thing. Then write the fake-response version, because that is the one that will still behave identically in six months on a machine with no network.

Why call raise_for_status() before json()?

If the ordering rule feels arbitrary, ask Monty to show what happens when a 404’s JSON body gets decoded as though it were a successful page. Seeing the wrong data arrive successfully is more convincing than the rule.

Task

Change request_json so it calls response.raise_for_status() before response.json() and catches nothing. Preserve the fixed URL, exact header, forwarded , one-call behavior, and explicit timeout.