Course progress0%
Course content
40 min

HTTP Is a Contract between Two Programs

Specify requests and responses before calling fetch

By the end of this lesson

  • Specify requests and responses before calling fetch
  • Separate transport failure, HTTP failure and invalid payloads

The request

"Load the product list from another program." Ask who owns product names and prices, what an empty list means, and what to display when that program is unavailable. A URL alone is not a contract.

For this module, build a local service. It owns a fictional catalogue. The browser fetches products and lets a learner inspect them. The existing manually entered quote still works independently. Server-authoritative order submission comes later.

Our first contract

Request Response Meaning
GET /api/products 200, JSON { "products": [...] } Available products
GET /api/products?mode=empty 200, JSON { "products": [] } Successful empty catalogue
GET /api/products?mode=error 503, JSON { "error": "unavailable" } Temporary service failure
Unknown route 404 No such resource

A product has an id, name and non-negative safe integer unitPriceCents. Product IDs must be unique. Extra fields may be ignored; missing or invalid required fields reject the response. An empty array is valid. Missing products is not an empty array.

Read a request before writing one

Open the Network panel. Identify the method, URL, status, content type and response body. JSON is a data representation, not proof that its values satisfy your contract. A server can return a valid JSON string where you expected an object.

A request has at least three failure boundaries: no usable response, an unsuccessful HTTP status, and a successful status with an unusable body. The person may see one recoverable message, while your development evidence distinguishes all three.

Do not use mode: 'no-cors' as a fix for unreadable JSON. In this lab the page and API will share one origin through one local server. Scheme, host and port together define that origin; two different ports are different origins.

Decide the interface states

Write the state model before code: idle, loading, ready, empty, error. Keep the catalogue state separate from the quote state. A catalogue failure must not erase the person's name or silently replace a selected price with zero.

Our initial policy clears old catalogue results when a new load starts. This avoids presenting stale data as current. A later stale-while-refreshing design is possible, but would need an explicit freshness label and rules about selecting stale products.

Evidence to submit

Sketch each of the five states and write one sentence describing the action available in it. For an empty catalogue, offer Reload and explain there are no products; for an error, offer Retry and explain the load failed. Those messages communicate different facts.

Your counterexample: a response of { "products": null } must trigger a contract error, not "No products available."

Lesson complete?

Your progress is saved on this device.