Home / Blog / URL HTTP & cURL

API & webhooks

REST Request and Response Headers: Inspect the Right Direction

Distinguish headers sent by the client from headers returned by the server, and understand why browser JavaScript may expose only part of a response.

Read a request and its response as separate messages

A request header is sent toward the server. A response header is returned toward the client. The same header name can appear in both directions while describing different content. For example, the request's Content-Type describes the submitted body, while the response's Content-Type describes the returned representation.

Keep the two messages separate in logs and debugging tools. A response header printed under a request heading can lead someone to change the wrong component. The client controls its permitted request fields, while the service and its intermediaries control the response fields they generate.

Compare an illustrative creation exchange

POST /notes HTTP/1.1
Host: api.example.com
Content-Type: application/json
Accept: application/json

{"title":"Map notes"}

HTTP/1.1 201 Created
Content-Type: application/json
Location: /notes/7
X-Request-ID: example-request-7

{"id":7,"title":"Map notes"}

The request declares the JSON it sends and the JSON response it can handle. The response identifies a created resource and supplies a correlation value. These example fields do not imply that every API returns Location or uses the same request-identifier name.

A relative Location value must be interpreted against the response's applicable URL context. Do not assume it names a local page on the front-end application's origin. When an application follows a returned link, retain its destination and credential policy rather than forwarding secrets to any URL in an untrusted response.

Inspect only what the browser actually exposes

async function readResponseDetails(url, fetcher = fetch) {
  const response = await fetcher(url);
  return {
    status: response.status,
    headers: Object.fromEntries(response.headers.entries()),
    body: await response.text()
  };
}

This function records a readable status, the exposed response-header entries and the response body as text. It does not reconstruct the outgoing request headers or reveal every header that was on the wire. It also does not treat a readable HTTP error as a network exception.

For large or sensitive responses, add limits and redaction appropriate to the application before retaining diagnostics. A general debugging helper should not place complete bodies or credentials into an ordinary analytics event. Render any retained body as text when displaying it.

Distinguish exposure from the response's existence

On a cross-origin response, browser JavaScript normally reads only the headers permitted by the CORS response rules. A server can use Access-Control-Expose-Headers to expose additional appropriate fields such as a request identifier. That response policy is separate from permission to send a custom request header.

A network panel may show a header that response.headers.get cannot read. This difference does not mean the JavaScript getter is broken or that the server omitted the field. Check the response's exposure policy, the request's origin and whether credentials are involved.

Some fields, notably Set-Cookie, are not made readable to front-end JavaScript by simply adding their names to an exposure list. Cookie processing belongs to the browser's cookie and credential rules. Do not design a browser token flow around reading Set-Cookie from a fetch response.

Identify where a header was added or changed

A reverse proxy, cache or application can add or modify response headers. If an expected value disappears between local development and production, compare the response at the appropriate boundaries. Editing the application handler may not fix a field overwritten by the hosting layer.

Request identifiers also require a consistent policy. Some systems accept and propagate a client-supplied value; others generate a server-controlled one. Use the documented correlation field and validate untrusted values before logging them. A header name by itself does not establish trustworthy provenance.

Test direction, exposure and subsequent requests

Use a local cross-origin fixture to return a custom header once without exposure and once with explicit exposure. Assert that browser-readable results differ as expected. Then send a second request with a different response value to ensure the display does not retain the earlier header.

The REST API Testing Tool labels its response section with the headers available to that browser. Use the request controls for outgoing values and the result section for returned values. Keep that distinction when sharing a redacted reproduction with the service owner.