انتقل إلى المحتوى
أمين أبوزيد
منشورBEG-052-L04

الترويسات (Headers)

  • الدرس 4 من 7
  • 10 دقيقة قراءة
  • مبتدئ
في هذا الدرس 11 موضوعات

هذا الدرس متاح حاليًا باللغة الإنجليزية فقط، ولم تُنشر نسخته العربية بعد.

Lesson Overview

On the restaurant slip, besides the dish itself you might write: "table 5", "no onions", "I speak French". On the dish's note, the kitchen might write: "contains nuts", "best before 8 pm". That extra information is not the order and not the dish: it is metadata, data about the message. In HTTP, metadata lives in headers.

Headers are the name-value lines between the first line and the blank line. They tell the receiver how to read the body, what the sender can accept, who the sender is, and how long a response may be reused.

This lesson explains the shape of a header and introduces the handful you will meet constantly: Host, Content-Type, Accept, Authorization, Cookie, Cache-Control, and Location. It builds on lesson 1 (where headers sit in a message) and BEG-003 (cookies as the way a stateless protocol remembers you).

Learning Objectives

By the end of this lesson you will be able to:

  • Write a header correctly as Name: value and know that names are case-insensitive.
  • Tell request headers from response headers.
  • Explain what Content-Type and Accept are for and how they differ.
  • Explain what Authorization carries and why it must never be shared.
  • Explain why Basic authentication is not encryption.
  • Recognize Host, Content-Length, Cookie, Set-Cookie, Cache-Control, Date, and Location.

Written Explanation

Shape of a header

A header is one line: a name, a colon, a value.

text
Content-Type: application/json

MDN states that header names are case-insensitive, so content-type and Content-Type mean the same thing. A request or response may have many headers, one per line. Their order mostly does not matter.

Headers fall into rough groups. Request headers give context about the request (Host, Accept, Authorization). Response headers give context about the response (Date, Server, Cache-Control). Representation headers, such as Content-Type and Content-Length, describe the body and appear in both directions.

The headers you will see most

HeaderDirectionWhat it says
HostRequestWhich host the request is for (api.example.com)
Content-TypeBothThe format of the body being sent
Content-LengthBothThe size of the body in bytes
AcceptRequestWhich formats the client is willing to receive
AuthorizationRequestCredentials proving who the client is
Cookie / Set-CookieRequest / ResponseThe mechanism for sessions on top of stateless HTTP
Cache-ControlResponse (also request)Rules for how long a copy may be reused
DateResponseWhen the response was generated
LocationResponseWhere to go: the new URL after a redirect, or where a created item lives

I verified Host, Content-Type, Content-Length, Accept, Authorization, Date, Cache-Control, and Location in MDN's pages; the direction and one-line descriptions of Cookie and Set-Cookie follow MDN's statement that cookies enable stateful sessions, and the exact header names are standard HTTP.

Content-Type and Accept: two sides of format

  • Content-Type describes the body that this message carries. A request that sends a book as JSON says Content-Type: application/json. A response that returns HTML says Content-Type: text/html.
  • Accept says what the client would like to receive. Accept: application/json means "please answer in JSON".

Restaurant version: Accept is "I would like the menu in French"; Content-Type on the dish's note is "this note is written in French". The pair lets the client and server agree on a format, which MDN calls content negotiation. If you forget Content-Type on a request that carries JSON, the server may not know how to read it and can answer 415 Unsupported Media Type, the code for exactly that situation.

The value application/json is a media type: a category (application, text, image) and a specific kind (json, html, png) separated by a slash. Sometimes a parameter follows, such as application/json; charset=utf-8.

Authorization: credentials

Authorization carries what proves who you are. Per MDN, the usual flow is: the client asks for a protected resource without credentials, the server answers 401, and the client tries again with an Authorization header such as:

text
Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l

With Basic, the credentials are a username and password joined by a colon and then Base64-encoded. Base64 is a way of writing bytes as text; it is not encryption. MDN warns that it is trivially reversible and recommends HTTPS, especially with Basic. Another common scheme, Bearer, sends a token instead of a password: Authorization: Bearer <token>. (MDN's Authorization page does not document Bearer; it is standardized elsewhere, in RFC 6750, which I did not open for this lesson.)

Treat this header like a password. Never paste it into chat, a screenshot, or a ticket. In BEG-003 you learned why HTTPS protects such headers in transit: without it, anyone along the path could read them.

Headers in a conversation

text
POST /books HTTP/1.1
Host: api.example.com
Content-Type: application/json
Accept: application/json
Authorization: Bearer <token>

{"title":"Dune"}

A server can read this as: "this is for api.example.com, I am sending JSON, I want JSON back, and here is my proof of identity." The matching response might add Content-Type: application/json, a Date, and Location: /books/8 pointing to the new item.

Who writes the headers?

Most of the time not you. A browser adds Host, Accept, Cookie, and others by itself, and a server framework adds Date and Content-Length. You set a header yourself when it carries a decision of yours: the Content-Type of the data you return, a Location for a created item, an Authorization token in a script that calls an API, or Cache-Control when you want to control reuse. Headers can also be custom: an application may invent its own names for its own purposes, and the receiver simply ignores names it does not know. This extensibility is what lets cookies and authentication sit on top of plain HTTP without changing the protocol.

Examples

Example 1: Read a header list (simple)

text
GET /books/7 HTTP/1.1
Host: api.example.com
Accept: application/json

Two headers. Host names the server; Accept says the client wants JSON. There is no Content-Type because there is no body to describe.

Example 2: Matching the format to the body (practical)

A client sends this:

text
POST /books HTTP/1.1
Host: api.example.com
Content-Type: text/plain

{"title":"Dune"}

The body is JSON text but the header says text/plain. A server that expects application/json may refuse it (typically with 415) or misread it. Fix the header: Content-Type: application/json. The lesson: the header must describe the body honestly, because the receiver trusts the header, not its own guess.

Example 3: Case-insensitive lookup in Java, and Base64 (realistic)

A server stores headers in a map. Since names are case-insensitive, the map must ignore case. Java's TreeMap accepts a comparator for that.

java
import java.util.Map;
import java.util.TreeMap;

public class L04 {
    public static void main(String[] args) {
        Map<String, String> headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
        headers.put("Content-Type", "application/json");
        headers.put("Accept", "application/json");
        System.out.println(headers.get("content-type"));
        System.out.println(headers.get("CONTENT-TYPE"));
        System.out.println(headers.get("Authorization"));
        System.out.println(headers.containsKey("accept"));
    }
}

Output (compiled and run with JDK 21):

text
application/json
application/json
null
true

A missing header gives null, so code that reads a header must handle absence (see the earlier lesson on null). Now the Base64 point: this program decodes the Basic value from above.

java
import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class L04b {
    public static void main(String[] args) {
        String header = "Basic YWxhZGRpbjpvcGVuc2VzYW1l";
        String encoded = header.substring("Basic ".length());
        byte[] bytes = Base64.getDecoder().decode(encoded);
        System.out.println(new String(bytes, StandardCharsets.UTF_8));
    }
}
text
aladdin:opensesame

Anyone who sees the header sees the password in three lines of code. That is why Basic needs HTTPS.

Backend Insight

Backend code reads request headers all the time: which format does the client want, who is calling, is a cached copy still fine. It also writes response headers: the content type of what it returns, where a new resource lives, how long to cache.

Two habits follow. First, always set Content-Type correctly on every response that has a body; a wrong one breaks clients in confusing ways. Second, never log whole header sets in production without hiding Authorization and Cookie: log files are often readable by many people, and copied credentials are a common source of leaks.

Missing headers are normal. A client may leave out Accept or Authorization, so your code needs a sensible default or a 401 for the missing credentials, not a crash on null.

Common Mistakes

Mistake 1: Confusing Content-Type and Accept

  • Incorrect: setting Accept: application/json to say "my body is JSON".
  • Correct: Content-Type describes the body I send; Accept describes what I want back.

Mistake 2: Sending a JSON body with the wrong or missing Content-Type

  • Incorrect: Content-Type: text/plain with a JSON body.
  • Correct: Content-Type: application/json.

Mistake 3: Thinking Base64 hides the password

  • Incorrect: "The Authorization header is encoded, so it is secret."
  • Correct: Base64 is reversible by anyone; secrecy comes from HTTPS and from not sharing the header.

Mistake 4: Comparing header names case-sensitively

  • Incorrect: headers.get("content-type") returns null in a plain HashMap because the key was stored as Content-Type.
  • Correct: use a case-insensitive map, or normalize the names.

Exercises

Level A: Foundation

A1. Write a header for each: the body is HTML; the client wants JSON; the server is shop.example.com.

أظهر الحل A1

A1. Content-Type: text/html; Accept: application/json; Host: shop.example.com.

A2. Is Accept a request header or a response header? Is Date?

أظهر الحل A2

A2. Accept is a request header. Date is a response header.

A3. Are Content-Type and content-type different headers?

أظهر الحل A3

A3. No: header names are case-insensitive, so they are the same header.

Level B: Application

B1. For a request POST /members that sends {"name":"Ana"} and wants JSON back, write the two headers it needs.

أظهر الحل B1

B1. Content-Type: application/json and Accept: application/json.

B2. A server answers 415 to a POST. Name the first header you check on the request, and why.

أظهر الحل B2

B2. Content-Type: 415 Unsupported Media Type means the server does not accept the body format, so a wrong or missing type is the first suspect.

B3. A teammate pastes a screenshot of the Network tab into a team chat, showing Authorization: Bearer ... in full. What is the problem, and what should be done?

أظهر الحل B3

B3. The header is a credential; anyone who sees it may use it until it expires. Delete the message, treat the token as exposed, and have it revoked or reissued by whoever manages it. In future, hide the value before sharing.

Level C: Challenge

C1. Write a Java method boolean isJson(Map<String,String> headers) that returns true when the Content-Type starts with application/json (so application/json; charset=utf-8 counts), returns false when the header is missing, and ignores header-name case. Show how you would test it with three cases.

أظهر الحل C1

C1.

java
static boolean isJson(Map<String, String> headers) {
    String type = headers.get("Content-Type");   // headers is a case-insensitive TreeMap
    return type != null && type.startsWith("application/json");
}

Tests: application/json gives true; application/json; charset=utf-8 gives true; a map without the header gives false (no NullPointerException, because of the type != null check). The map must be created with String.CASE_INSENSITIVE_ORDER, as in Example 3. (Compiled and run with the three cases: true, true, false.)

C2. Explain what happens if a response sends a JSON body but with Content-Type: text/html, and who gets confused.

أظهر الحل C2

C2. A client that trusts the header will treat the body as an HTML page, not as data, so a program expecting JSON may fail to parse it, and a browser may show raw text or try to render it. The sender, not the receiver, is at fault: the header must describe the body honestly.

Mini Challenge

Write a complete request and response for creating a member in a club API. Include: the request line, at least four sensible request headers, a JSON body; and the response status line, at least three response headers (one must be Location), and a JSON body.

Check your work: Content-Type matches each body; Accept appears on the request; there is a blank line before each body; the status is 201; and you included no real credentials (use <token> as a placeholder).

Summary & Next Lesson

Key takeaways

  • A header is a Name: value line; names are case-insensitive.
  • Content-Type says what the body is; Accept says what the client wants back.
  • Authorization carries credentials and must be treated like a password. Base64 is not encryption.
  • Host, Content-Length, Cookie, Set-Cookie, Cache-Control, Date, and Location are common companions.
  • Backend code must handle headers that are missing.

Next lesson

The next lesson, "JSON", looks at the data format that usually travels in the body and that Content-Type: application/json announces.

Self-check

  1. Which header says the body is JSON?
  2. What is Accept for?
  3. Why is Authorization: Basic ... not secret by itself?
  4. Are header names case-sensitive?
  5. Which header tells the client where a newly created item lives?
أظهر الإجابات
  1. Content-Type: application/json.
  2. It tells the server which formats the client is willing to receive.
  3. Base64 can be decoded by anyone; only HTTPS protects it in transit.
  4. No.
  5. Location (a common choice, as in MDN's 201 Created example).

References

  • MDN: HTTP messages. Supports header syntax, case-insensitivity, request/response/representation header groups, the Location header in a 201 example, and Content-Length.
  • MDN: Content negotiation. Supports what Accept does; the fetched text only touched Content-Type in passing, so its description here comes from general HTTP knowledge.
  • MDN: Authorization header. Supports the 401 flow, the Basic scheme with Base64, the decoded example, and the HTTPS warning.
  • MDN: An overview of HTTP. Supports cookies as the way to add sessions to stateless HTTP.

التطبيق

طبّق هذا الدرس بمختبر الوحدة وتمارينها واختبارها.

المختبر والتمارين الاختبار

تعليم الدرس كمكتمل اختياري ويمكنك التراجع عنه في أي وقت. يبقى تقدمك محفوظًا في هذا المتصفح.

اكتب للبحث في المستويات والمراحل والوحدات والدروس.