DevTools · Lekcja 02

Co mówi zakładka Network? Jak sprawdzić żądanie i odpowiedź API

Ćwiczenie do tej lekcji jest gotowe do uruchomienia w tym serwisie. Otwórz laboratorium → Instrukcje uruchomienia terminala w tekście dotyczą również samodzielnej pracy na plikach źródłowych.

Klikasz „Utwórz konto”, a formularz pokazuje sukces. W pierwszej lekcji nauczyłeś się porównywać ten komunikat z wymaganiem i stanem kont. Teraz przyjrzysz się drodze pomiędzy kliknięciem a wynikiem. Ustalisz, które żądanie wywołała Twoja akcja, co aplikacja wysłała i co otrzymała. Dzięki temu zapis „rejestracja nie działa” zastąpisz konkretną obserwacją.

Pracujemy na tym samym lokalnym formularzu demonstracyjnym v1.0. Potrzebujesz podstawowej obsługi przeglądarki i terminala; nie musisz umieć programować. Przykładowe adresy i hasła są fikcyjne. Celem lekcji jest analiza pojedynczej wymiany z API, czyli interfejsem, przez który formularz komunikuje się z serwerem. Nie będziemy projektować API ani wykonywać testów obciążeniowych.

1. Przygotuj zapis jednej próby

Uruchom serwer w katalogu projektu:

node tools/serwer-lekcji.cjs

Otwórz formularz pod adresem http://127.0.0.1:8787/content/cwiczenia/formularz-rejestracji/lab.html. Jeśli serwer już działa, użyj istniejącego procesu. Dokładne wymagania i sposób resetowania znajdziesz w instrukcji ćwiczenia. Samo odświeżenie strony nie usuwa kont z pamięci serwera.

Otwórz DevTools skrótem Ctrl+Shift+I, wybierz Network i sprawdź, czy rejestrowanie jest włączone. Otwieraj narzędzie przed badaną akcją. Network nie odtworzy wcześniejszej próby, której nie zarejestrował. Wybierz Fetch/XHR: w tym demo pozwoli to skupić się na wywołaniach API. Ustaw sieć No throttling, wyłącz symulację 503 i kliknij „Resetuj ćwiczenie”. Poczekaj na potwierdzenie resetu, a potem wyczyść listę Network przyciskiem Clear.

Przygotowanie panelu opisuje oficjalny samouczek Chrome DevTools. Nazwy podajemy po angielsku; układ przycisków zależy od wersji przeglądarki. Zanotuj jej wersję wraz z datą testu.

Clear usuwa wpisy z widoku, a reset ćwiczenia zmienia dane na serwerze. To dwie różne czynności. Po czyszczeniu nie musisz odświeżać formularza: zrobisz jedną akcję na już wczytanej stronie. Taki punkt startowy pomaga odróżnić ruch związany z kliknięciem od ruchu towarzyszącego ładowaniu strony.

2. Dopasuj kliknięcie do żądania

Wpisz network@example.com, w obu polach hasła abcdefghijkl, zaznacz regulamin DEMO i świadomie wyłącz marketing. Wyślij formularz raz. W obecnym kodzie ta akcja wywołuje POST /api/register, a po jej zakończeniu aplikacja próbuje pobrać stan przez GET /api/state.

Nie wybieraj ostatniego wpisu tylko dlatego, że pojawił się najbliżej komunikatu. state pobiera konta; nie tworzy nowego konta. Wpisz register w filtrze tekstowym i wybierz żądanie rejestracji. Potwierdź pełny URL w szczegółach: http://127.0.0.1:8787/api/register. W razie niejasności usuń filtr i porównaj oba wywołania.

Request oznacza żądanie wysłane przez przeglądarkę, a response — odpowiedź otrzymaną dla niego. Jedno kliknięcie może inicjować kilka wywołań, każde z własnym wynikiem. Lista żądań pokazuje ten przepływ, ale nie przypisuje automatycznie wszystkim wpisom znaczenia „rejestracja”. Takie znaczenie ustalasz z adresu, metody, danych i momentu wykonania.

Akcja w interfejsie wywołuje żądanie zawierające metodę, URL, nagłówki i dane; odpowiedź zawiera status, nagłówki i treść, a wynik trzeba porównać z UI i stanem

Czytaj obie strony wymiany i porównuj je z efektem w aplikacji. Odpowiedź serwera oraz komunikat formularza są osobnymi dowodami.

3. Przeczytaj URL, metodę i nagłówki

W szczegółach wybranego wpisu otwórz Headers. Zacznij od części General, a następnie sprawdź Request Headers i Response Headers. Rozdzielenie tych części ma znaczenie: nagłówek wysłany przez klienta nie jest automatycznie nagłówkiem odpowiedzi.

ElementW tej próbieCo z niego wynika
Request URLhttp://127.0.0.1:8787/api/registerŻądanie dotyczy lokalnego endpointu rejestracji
Request MethodPOSTWywołano operację rejestracji zgodną z umową demo
Status Code201 przy poprawnej próbieSerwer zgłosił utworzenie zasobu
Request Headers: Content-Typeapplication/jsonKlient deklaruje wysyłanie JSON
Response Headers: Content-Typeapplication/json; charset=utf-8Serwer deklaruje odpowiedź JSON w UTF-8
Response Headers: Cache-Controlno-storeOdpowiedź nie powinna być przechowywana w cache HTTP

JSON to tekstowy format danych z nazwami pól i wartościami. Sam nagłówek Content-Type nie potwierdza, że treść jest poprawna ani zgodna z umową API. W tym laboratorium możesz porównać deklarację z rzeczywistym body, czyli treścią wiadomości.

Metodę interpretuj razem z endpointem: POST /api/reset resetuje stan, a POST /api/register tworzy konto. Samo POST nie dowodzi poprawnej rejestracji. Podobnie status 200 z GET /api/state potwierdza odpowiedź odczytu stanu, a nie powodzenie wcześniejszego zapisu.

4. Porównaj Payload z formularzem

Otwórz Payload i odczytaj Request Payload. Dla przygotowanych danych kod demo wysyła taki obiekt:

{
  "email": "network@example.com",
  "password": "abcdefghijkl",
  "confirm": "abcdefghijkl",
  "terms": true,
  "marketing": false,
  "simulate503": false
}

To przykład wynikający z kodu laboratorium, nie eksport czyjejś sesji. Porównaj wszystkie pola z własną próbą. true i false to wartości logiczne, a nie teksty w cudzysłowach. simulate503 jest technicznym przełącznikiem demonstracji, nie elementem produkcyjnej rejestracji.

Zwróć uwagę na e-mail. Formularz obcina spacje na jego początku i końcu przed wysłaniem. Jeśli wpiszesz network@example.com, Payload powinien zawierać adres bez tych spacji. Taka różnica może być realizacją wymagania. Z kolei marketing: true przy świadomie odznaczonym checkboxie byłoby sprzecznością wymagającą wyjaśnienia.

Obecność pola confirm nie dowodzi, że backend porównuje hasła. Network potwierdza wysłaną wartość; egzekwowanie reguły ustalisz z odpowiedzi i skutku testu. W pierwszej lekcji ten brak kontroli jest jednym z celowych defektów.

W innym API Payload może pokazywać parametry adresu albo dane formularza zamiast JSON. Nie przenoś formatu tej demonstracji na wszystkie produkty. Sposób prezentacji zależy od badanego żądania.

5. Czytaj Response razem ze statusem i stanem

Otwórz Response. Poprawna rejestracja z wyłączonym marketingiem zwraca w demo:

{"created":true,"email":"network@example.com","marketing":false,"demo":true}

Porównaj e-mail z Payload. Następnie usuń filtr register, wybierz następujący po rejestracji GET /api/state i sprawdź, czy tablica emails zawiera adres, a obiekt marketing przypisuje mu false. Możesz też odczytać stan w panelu ćwiczenia. Konto istnieje tylko w RAM procesu serwera; nie jest to dowód zapisu do trwałej bazy.

Wyślij ten sam adres ponownie bez resetowania. W tym scenariuszu oczekujesz 409 oraz treści {"error":"Ten adres e-mail jest już zajęty."}. Konto nie powinno zostać dodane drugi raz. Wynik 409 jest poprawną realizacją reguły unikalności dla tej próby, choć należy do klasy błędów HTTP klienta. Czerwony wpis nie oznacza automatycznie defektu aplikacji.

Próba w demoOdpowiedź APIPrawidłowa interpretacja
Nowy adres i poprawne dane201, created: truePorównaj ze stanem i sukcesem UI
Adres już istnieje409, pole errorKonflikt; nie twórz kolejnego konta
Dane odrzucone przez backend422, pole errorWalidacja serwera nie przeszła
Włączona symulacja awarii503, pole errorSerwer odpowiedział błędem; konto nie powstało
DevTools ustawione na OfflineNieudane wywołanie bez odpowiedzi HTTPBadaj połączenie i ustawienia; nie dopisuj statusu 503

W tym labie jest celowy defekt: formularz traktuje odpowiedź 503 jako sukces. Network pozwala udokumentować sprzeczność między błędem API, komunikatem UI i brakiem konta. Mechanizm fetch() wyjaśnia, dlaczego samo odebranie odpowiedzi nie wystarcza: błędny status HTTP nie odrzuca automatycznie obietnicy, natomiast kod może sprawdzić response.ok lub response.status. MDN: Using the Fetch API.

6. Sprawdź Timing i Initiator bez zgadywania przyczyny

Otwórz Timing dla rejestracji. W demo backend celowo czeka około 500 ms przed odpowiedzią, więc test nie powinien oczekiwać wyniku natychmiast. Zapisz własny zmierzony czas. Nie wpisuj „dokładnie 500 ms”: pomiar obejmuje także inne czynności i zależy od środowiska.

Waiting (TTFB) opisuje oczekiwanie na pierwszy bajt, obejmujące opóźnienie komunikacji oraz przygotowanie odpowiedzi. Content Download dotyczy odbioru treści. Nie każda faza pojawi się w każdym wywołaniu; połączenie może zostać użyte ponownie. Długi TTFB jest punktem startowym dalszego badania, nie dowodem na wolną bazę danych. W naszym demo wyjaśnienie opóźnienia znamy z kodu.

Initiator pomaga znaleźć kod inicjujący żądanie. Sprawdź tę kolumnę lub zakładkę szczegółów i przejdź do wskazanej funkcji. Dla register szukaj obsługi wysłania formularza i wywołania fetch('/api/register', ...); dla state — funkcji state(). Nie potrzebujesz zapamiętanego numeru linii, ponieważ zmieni się po edycji pliku.

Widoki szczegółów i fazy czasu opisuje referencja Network. Własny wniosek z laboratorium jest węższy: potrafisz wskazać źródło wywołania i miejsce oczekiwania, ale sam panel nie pokazuje czasu każdej operacji wewnątrz backendu.

7. Rozróżnij trzy sytuacje diagnostyczne

Nie widzisz wpisu. Najpierw usuń filtry, wybierz All, sprawdź rejestrowanie i powtórz akcję. Dopiero przy poprawnym zapisie badaj, czy formularz w ogóle doszedł do wysyłki. W labie wpisanie qa@ wywołuje komunikat walidacji JavaScript przed fetch(). Wtedy opisujesz zablokowanie wysłania przez formularz, a nie odrzucenie przez serwer. Brak wpisu w przefiltrowanej liście nie jest jeszcze dowodem braku żądania.

Widzisz odpowiedź HTTP. Odczytaj status, body i skutek. 422 i 503 nie są tym samym scenariuszem. Pierwszy oznacza odrzucenie danych zgodnie z umową tego API, drugi symulowaną awarię. Przy nieudanej operacji sprawdź też, czy UI umożliwia poprawę danych albo ponowienie próby.

Wpis jest nieudany, bez odpowiedzi HTTP. Sprawdź ustawienie Offline, działanie serwera i szczegóły błędu w Console. Po wczytaniu formularza ustaw Offline i wyślij poprawne dane. W obecnym demo zawiedzie także późniejszy odczyt stanu. Przywróć No throttling i odśwież stronę, aby pobrać stan ponownie; formularz nadal nie powinien był utworzyć konta w tej próbie.

Drzewo diagnozy: przy braku wpisu sprawdź filtry, rejestrowanie i wysłanie formularza; przy odpowiedzi HTTP sprawdź status, treść i stan; przy braku HTTP sprawdź Offline, sieć i Console

Najpierw ustal, co zarejestrowano. Dopiero później nazwij problem i wybierz następny krok.

W prawdziwej aplikacji nieudane wywołanie może też wiązać się z CORS, mechanizmem ograniczającym dostęp skryptu do odpowiedzi z innego originu. Origin uwzględnia schemat, host i port. Sam napis (failed) nie uzasadnia diagnozy „CORS”; potrzebujesz szczegółów, w tym komunikatu Console. Nasz formularz i API działają pod tym samym originem, więc nie przygotowujemy tu scenariusza CORS. MDN: CORS.

8. Utrzymuj log i świadomie ustawiaj cache

Preserve log zachowuje wpisy przy przeładowaniu lub nawigacji. Przydaje się, gdy akcja przenosi użytkownika na inną stronę. Nie resetuje serwera ani nie odzyskuje niezarejestrowanej historii. W tym demo formularz pozostaje na stronie, więc do pojedynczej próby wystarczy świadome czyszczenie listy. Zachowane stare wpisy oznacz, aby nie policzyć ich jako nowych prób.

Disable cache wyłącza cache przeglądarki podczas pracy z otwartymi DevTools. Nie jest resetem kont, nie czyści danych aplikacji ani nie wyłącza cache serwera. Zapisz ustawienie użyte podczas testu, bo wpływa na warunki obserwacji. Funkcje te opisuje dokumentacja panelu Network.

Ten serwer ustawia Cache-Control: no-store zarówno dla API, jak i plików strony. Dlatego nie obiecujemy tu zobaczenia odpowiedzi „from memory cache”, „from disk cache” ani różnicy po przełączeniu Disable cache. Możesz sprawdzić nagłówek; demonstracja porównania cache wymagałaby innego zasobu. no-store oznacza zakaz przechowywania odpowiedzi w cache HTTP; no-cache pozwala ją przechowywać, ale wymaga walidacji przed ponownym użyciem. MDN: Cache-Control.

9. Zadanie: zbierz dowody z czterech prób

Wykorzystaj istniejące ćwiczenie oraz checklistę, dostępną również jako PDF. Dodaj do notatek osobne zadanie analizy sieci. Przed każdą niezależną próbą resetuj demo, przywracaj No throttling i czyść log.

  1. Utwórz analiza@example.com z poprawnymi hasłami i wyłączonym marketingiem. Zapisz URL, metodę, oba Content-Type, Payload, status, Response, czas i Initiator. Porównaj rezultat z GET /api/state.
  2. Bez resetowania wyślij ten sam adres jeszcze raz. Porównaj odpowiedź ze stanem.
  3. Resetuj, włącz „Błąd serwera 503” i powtórz poprawne dane. Zanotuj osobno UI, API i stan.
  4. Resetuj w trybie online, następnie ustaw Offline i wyślij poprawne dane. Po przywróceniu sieci odśwież formularz i sprawdź stan. Wyjaśnij, czym dowód tej próby różni się od poprzedniej.

Osobno porównaj brak żądania z walidacją backendu: wpisz w formularzu qa@ i obserwuj log. Następnie, przy działającym serwerze i sieci online, wyślij syntetyczne dane bezpośrednio do API przez Console:

fetch('/api/register', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    email: '', password: 'abcdefghijkl', confirm: 'abcdefghijkl',
    terms: true, marketing: false, simulate503: false
  })
}).then(async response => console.log(response.status, await response.json()));

Przeczytaj kod przed uruchomieniem. Dotyczy wyłącznie lokalnego demo. To dodatkowa próba API, nie wysłanie formularza; jej Initiator wskaże Console. Po niej UI nie pobierze sam stanu. Jeśli potrzebujesz nowego odczytu, odśwież stronę.

10. Rozwiązanie i sposób zapisu wniosku

Pierwsza próba powinna dać 201, created: true i konto analiza@example.com z marketingiem false. Kolejne wysłanie daje 409; konto pozostaje jedno. Próba 503 zwraca {"error":"Symulowana awaria serwera. Konto nie powstało."}. Obecny frontend mimo to pokazuje sukces — to celowy defekt, który potwierdza porównanie ze stanem.

Offline powinno przerwać wywołanie bez odpowiedzi HTTP. Nie wpisuj 503 ani domniemanego body. Zapisz widoczny błąd Network i komunikat UI, a stan sprawdź po powrocie online. Błędny e-mail w formularzu blokuje wysyłkę. Bezpośrednia próba z pustym e-mailem dociera do API i otrzymuje 422 z komunikatem Podaj e-mail w formacie nazwa@domena.pl.. To różne miejsca walidacji i różne dowody.

Przykładowy wniosek brzmi: „Dla POST /api/register z simulate503=true API zwróciło HTTP 503 i komunikat o nieutworzeniu konta. UI pokazało sukces, a kolejny GET /api/state nie zawierał adresu testowego”. Uzupełnij go rzeczywistą datą, wersją przeglądarki i wynikami własnej próby. Przed udostępnieniem zrzutów lub eksportu ruchu sprawdź ich treść: Payload może zawierać hasło, a prawdziwe żądania również tokeny i dane osobowe.

Źródła odczytano 2 października 2026 r. Tego dnia automatycznie sprawdzono scenariusze laboratorium v1.0 w Node v24.16.0 i Chromium 151.0.7922.34: odpowiedzi 201/409/422/503, wysyłane dane, nagłówki, blokadę wysyłki przy pustych polach i Offline bez odpowiedzi HTTP. Potwierdzono fałszywy sukces UI przy 503 oraz brak konta. Nie wykonano ręcznej kontroli interfejsu panelu DevTools; opis Timing nie jest benchmarkiem. Autor serwisu: Marcin Kozłowski. Research i tekst przygotowano z pomocą AI. W tej lekcji nie przeprowadzono pełnej oceny bezpieczeństwa, wydajności ani obsługi CORS.

Research i przygotowanie tekstu z pomocą GPT-6.1 Sol, reasoning medium.