Course outline · 0% complete

0/25 lessons0%

Course overview →

Anatomy of an HTTP response

lesson 4-2 · ~10 min · 11/25

What comes back

The server answers with the same text format, just a different first line:

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1256

<html> ...the page itself... </html>
  1. Status line: VERSION CODE REASON. The status code 200 is the machine-readable result, and OK is the human-readable label.
  2. Headers, again Name: value. Content-Type says what the body is, because the client handles each format differently. text/html is a web page to render, image/png is picture bytes to display, and application/json is JSON, short for JavaScript Object Notation, a plain-text format for structured data that looks like {"user": "ada"} and is the standard language of APIs. Lesson 4-4 covers it properly. Content-Length says how many bytes the body is, so the client knows when it has everything.
  3. Blank line, then the body: the actual page, data, or image bytes.

Everything your browser shows you arrived as the body of some response. The headers are invisible to users but they are the first thing an engineer reads when debugging, because they tell you what the server thinks it sent.

Reading the status line

A response is stored in a variable, and the script pulls out its code, which is the first thing every HTTP client library does.

response="HTTP/1.1 404 Not Found
Content-Type: text/html
Content-Length: 1207

<html>...page not found...</html>"

status_line=$(echo "$response" | head -n 1)
code=$(echo "$status_line" | cut -d' ' -f2)

echo "status line: $status_line"
echo "code: $code"

Output

status line: HTTP/1.1 404 Not Found
code: 404

head -n 1 takes the first line, and cut -d' ' -f2 takes the second space-separated field, which is the code.

Notice that a 404 still has a body, and Content-Length: 1207 says it is a substantial one. An error response is a normal response with an unhappy code, usually carrying a human-readable page explaining the problem.

That is a distinction worth keeping straight while debugging. A 404 means the exchange worked perfectly and the answer was "no such thing", which is very different from a connection that never completed.

Extracting code and headers together

Three values out of one stored response: the status code, the Content-Type, and the Content-Length.

response='HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 27

{"user":"ada","plan":"pro"}'

code=$(echo "$response" | head -n 1 | cut -d' ' -f2)
ctype=$(echo "$response" | grep '^Content-Type:' | cut -d' ' -f2)
clen=$(echo "$response" | grep '^Content-Length:' | cut -d' ' -f2)

echo "code: $code"
echo "type: $ctype"
echo "length: $clen"

Output

code: 200
type: application/json
length: 27

Reading the pipelines

  • The code is field 2 of line 1, so head -n 1 narrows to the line and cut -d' ' -f2 picks the field.
  • For each header, grep matches its name with a leading ^ so the pattern only matches at the start of a line, then cut takes field 2. The anchor matters, since Content-Type also appears as a substring in other contexts.
  • Each pipeline is wrapped in $( ... ) to store its output in a variable rather than print it.
  • Counting the body confirms the header: {"user":"ada","plan":"pro"} is exactly 27 characters, which is how the client knows it has read everything and can stop.

What Content-Type: application/json tells a client

It says the body should be parsed as JSON data, not displayed as a web page.

Content-Type describes the body's format so the client knows what to do with it. It renders text/html as a page, parses application/json as data, and displays image/png as a picture.

The header is a claim rather than a guarantee. A server can label JSON as text/plain by mistake, and the client will then hand you a string where you expected an object, which is a common cause of a confusing parse error.

APIs almost always speak application/json, which you will drive with curl in unit 5.