Request i Response: co faktycznie wysyła browser?
Frontend pisze:
await fetch("/api/users/42");
Na poziomie HTTP intencja wygląda mniej więcej tak:
GET /api/users/42
Ale request to nie URL.
Semantycznie składa się z:
method
target
headers
optional content
Response analogicznie:
status
headers
optional content
Request
Przykład uproszczony do HTTP/1.1 notation:
GET /api/users/42 HTTP/1.1
Host: example.com
Accept: */*
Cookie: session=...
Browser może dodać część headers sam.
JavaScript nie konstruuje surowego pakietu sieciowego.
Wywołuje browser API:
JavaScript
|
v
Fetch
|
v
browser builds HTTP request
To rozróżnienie będzie wracało przez całą serię.
Response
Backend może odpowiedzieć:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 24
{"id":42,"name":"Alice"}
W fetch() najpierw dostajemy obiekt Response:
const response = await fetch(url);
response.status;
response.headers;
A body konsumujemy osobno:
const user = await response.json();
To nie jest przypadek.
Headers i body mają osobny lifecycle.
fetch() resolve nie oznacza 200
Jeżeli backend odpowie:
HTTP/1.1 404 Not Found
browser dostał poprawną odpowiedź HTTP.
Dlatego:
const response = await fetch("/missing");
console.log(response.status); // 404
console.log(response.ok); // false
Promise nie musi zostać odrzucony.
Dla Fetch API:
HTTP error response
!=
network failure
To bardzo ważna granica.
404 i 500 są informacją wewnątrz HTTP.
Brak możliwej do udostępnienia odpowiedzi jest inną klasą problemu.
Body nie zawsze istnieje
Frontend często zakłada:
response = JSON
Ale HTTP response może nie mieć content.
Przykład:
HTTP/1.1 204 No Content
Kod:
await response.json();
nie ma wtedy czego parsować.
API client powinien więc rozumieć kontrakt endpointu, a nie automatycznie traktować każdy sukces jako JSON.
HTTP message to abstrakcja
W HTTP/1.1 request wygląda na wire mniej więcej jak tekst, który pokazaliśmy.
W HTTP/2 request jest zakodowany jako binary frames.
W HTTP/3 również nie jest wysyłany jako tekstowa linia:
GET /api/users/42 HTTP/1.1
Mimo to semantycznie nadal jest:
GET
/api/users/42
headers
Dlatego DevTools pokazuje nam logiczny HTTP request, niekoniecznie bajty lecące po sieci.
To prowadzi do następnego pytania.
Skoro GET, POST, 404 i 500 są częścią semantyki HTTP, to co dokładnie znaczą i dlaczego browser oraz infrastruktura mogą zachowywać się inaczej zależnie od metody i statusu?