Headers i Body: metadane kontra reprezentacja
Typowy request:
fetch("/api/users", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
name: "Alice"
})
});
Łatwo potraktować Content-Type jak boilerplate.
Nie jest nim.
Body to bytes, nie JSON
Dla HTTP body jest contentem przesyłanym jako sekwencja bajtów.
To header mówi odbiorcy, jak je interpretować:
Content-Type: application/json
Inne możliwości:
text/plain
text/html
application/octet-stream
multipart/form-data
image/webp
HTTP nie wymaga JSON-a.
JSON jest wyborem warstwy aplikacyjnej.
Content-Type opisuje to, co wysyłamy
Content-Type: application/json
oznacza:
content tej wiadomości jest JSON-em.
Natomiast:
Accept: application/json
oznacza:
klient preferuje JSON jako reprezentację response.
To dwa różne kierunki negocjacji.
Content-Type -> what I am sending
Accept -> what I want back
Browser potrafi zbudować body za nas
Dla FormData:
const form = new FormData();
form.append("name", "Alice");
form.append("avatar", file);
fetch("/profile", {
method: "POST",
body: form
});
Nie powinniśmy ręcznie ustawiać:
Content-Type: multipart/form-data
Browser musi dodać poprawny boundary.
Przykładowo:
multipart/form-data; boundary=----browser-generated
To przykład sytuacji, w której ręczna kontrola nad HTTP pogarsza request.
Content-Encoding jest inną warstwą
Response może mieć:
Content-Type: application/json
Content-Encoding: gzip
Semantycznie reprezentacja jest JSON-em.
Na wire content został dodatkowo zakodowany kompresją.
Browser zwykle dekompresuje go przed udostępnieniem przez Fetch API.
Frontend dostaje:
await response.json();
a nie skompresowane bajty gzip do ręcznego rozpakowania.
Content-Length nie zawsze jest potrzebny
Jeżeli rozmiar content jest znany, może pojawić się:
Content-Length: 842
Ale streaming response może być produkowany stopniowo.
Wtedy pełny rozmiar nie musi być znany na początku.
To ważne dla frontendu:
response headers available
!=
entire body downloaded
Dlatego Response.body może być ReadableStream.
Headers sterują zachowaniem browsera
Headers nie są tylko metadata dla backendu.
Mogą wpływać na:
cache
cookies
content interpretation
redirects
CORS
download behavior
security policy
Ale JavaScript nie ma nad nimi pełnej kontroli.
Browser jest aktywnym uczestnikiem HTTP i część requestu buduje sam.
To będzie tematem następnego artykułu.