Podręcznik

Express

Trasowanie

Obiekt app, utworzony za pomocą polecenia express(), dysponuje metodami odpowiadającymi metodom HTTP: get, post, put, delete itd. Za pomocą tych metod można określać trasy, które będą obsługiwane przez aplikację serwerową. Każda z tych metod wymaga podania co najmniej dwóch argumentów wejściowych:

  • ścieżki (ang. path),
  • funkcji (nazywanej po angielsku route handler, co nie ma powszechnie przyjętego polskiego odpowiednika) wywoływanej po nadejściu żądania zawierającego daną ścieżkę i metodę HTTP.
app = express();
app.[metoda]([ścieżka], [route_handler]);

Jeśli, przykładowo, chcemy, aby żądanie metodą GET dla ścieżki /hello poskutkowało wysłaniem w odpowiedzi tekstu "Hello, world", to można to zrealizować w następujący sposób:

app.get('/hello', (req, res) => {
  res.send('Hello, world');
});

W najprostszym przypadku, funkcja stanowiąca route handler powinna przyjmować dwa argumenty wejściowe, typowo nazywane req i res (od ang. request i response):

  • pierwszy argument wejściowy reprezentuje przychodzące żądanie,
  • drugi argument wejściowy reprezentuje odpowiedź, która zostanie wysłana przez aplikację serwerową.

Określanie ścieżek

Ścieżka, stanowiąca pierwszy argument metody app.get, app.post itp., może być podana w formie wyrażenia regularnego (ang. regular expression). Przykładowo, poniższe polecenie:

app.get('^/$|/index(.html)?', handler);

przypisze funkcję handler do wszystkich trzech następujących ścieżek:

  • /
  • /index
  • /index.html

Trasy, zdefiniowane w kodzie aplikacji serwerowej, są podczas trasowania sprawdzane po kolei, a gdy jakaś trasa okaże się pasować do żądania, to dalsze nie będą już sprawdzane. Na końcu pliku można więc umieścić kod obsługujący wszystkie nieprzewidziane trasy:

// ...
// obsługa różnych przewidzianych tras
// ...

app.get("/*", (req, res) => unexpected_route_handler);

"/*" oznacza tu dowolną ścieżkę zaczynającą się od ukośnika.


Konstruowanie odpowiedzi

Odpowiedzi na żądania należy konstruować i wysyłać za pomocą metod obiektu res (będącego jednym z argumentów wejściowych metod takich jak app.get, app.post, ...). Do metod generujących odpowiedzi należą m.in.:

  • res.send, służąca do wysyłania różnego rodzaju odpowiedzi, w tym prostego tekstu;
  • res.sendFile, służąca do wysyłania plików;
  • res.redirect, służąca do przekierowywania żądań;
  • res.download, służąca do zlecania pobrania pliku.

Wywołanie dowolnej z powyższych metod skutkuje wysłaniem odpowiedzi i zakończeniem przetwarzania żądania. Jeśli żadna taka metoda nie zostanie wywołana, to żądanie może pozostać bez odpowiedzi.

Przykładowo, jeśli w odpowiedzi na żądanie GET ze ścieżką /contact ma być przesłany plik contact.html, zapisany w folderze views, to można to zrealizować w następujący sposób:

const path = require('path')

// ...

app.get("/contact", (req, res) => {
  res.sendFile(path.join(__dirname, "views", "contact.html"));
});

Kody odpowiedzi

Express automatycznie dobiera kody odpowiedzi (np. 200 – OK, 404 – Not Found itp.). Można jednak również samemu ustalić kod za pomocą metody res.status. Przykładowo, jeśli w odpowiedzi na nieprzewidzianą ścieżkę chcemy wysłać przygotowany specjalnie na taką okazję plik not_found.html, zapisany w folderze views, to powinniśmy opatrzyć go kodem 404; można to zrealizować w następujący sposób:

res.status(404).sendFile(path.join(__dirname, 'views', 'not_found.html'));

Przekierowanie za pomocą metody res.redirect domyślnie opatrzone jest kodem 302 (oznaczającym przekierowanie tymczasowe). Przekierowanie z kodem 301 (sygnalizującym, że adres został zmieniony na stałe) można zrealizować w następujący sposób:

res.redirect(301, [nowy_adres]);

Przykład

Poniższy fragment kodu stanowi zebranie wcześniejszych przykładów i implementuje prostą aplikację serwerową. Aplikacja ta:

  • W odpowiedzi na żądanie GET pod dowolną ze ścieżek: /, /index lub /index.html wysyła plik index.html, zapisany w folderze views, z kodem 200;
  • W odpowiedzi na wszelkie inne żądania GET wysyła plik not_found.html, zapisany w folderze views, z kodem 404.
const path = require('path')
const express = require('express');
const app = express();
const port = 3000;

app.get("^/$|/index(.html)?", (req, res) => {
  res.sendFile(path.join(__dirname, "views", "index.html"));
});

app.get("/*", (req, res) => {
  res.status(404).sendFile(path.join(__dirname, "views", "not_found.html"));
})

app.listen(port, () => console.log(`Aplikacja serwerowa działa na porcie ${port}.`));

Więcej informacji: