MIDDLEWARE czyli oprogramowanie pośredniczące jest to rodzaj oprogramowania/funkcji umożliwiającej komunikację pomiędzy różnymi aplikacjami, usługami lub systemami.
middleware
middleware
app
REQUEST
RESPONSE
Middleware w Express pełni rolę pośrednią przed wykonaniem odpowiedniej instrukcji dla danej ścieżki.
W funkcji mamy dostęp do żądania i odpowiedzi HTTP oraz funkcji callback next, która odpowiada za wywołanie kolejnego middleware lub przejścia do odpowiedniej instrukcji dla danej ścieżki.
Funkcje middleware mogą wykonywać następujące zadania:
const express = require('express');
const app = express();
const customMiddleware = (req, res, next) => {
// some logic ...
next();
};
app.use(customMiddleware);
app.listen(4500, () => console.log('server started'));Jeżeli middleware nie kończy żądania/odpowiedzi, musi zostać wywyłana funkcja next(), aby przekazać sterowanie do następnej funkcji oprogramowania pośredniego.
W przeciwnym wypadku żądanie zostanie zawieszone.
// ...
const timeMiddleware = (req, res, next) => {
req.requestTime = new Date();
next();
};
app.use(timeMiddleware);
app.get('/', (req, res) => {
res.send('request time: ' + req.requestTime);
});
// ...W Express możemy wykorzystać takie typy middleware jak:
Powiązanie oprogramowania warstwy pośredniej na poziomie aplikacji.
Ten rodzaj middleware będzie wykonywał się dla całej aplikacji lub dla wydzielonej grupy ścieżek.
const express = require('express');
const app = express();
app.use((req, res, next) => {
console.log('current time', new Date());
next();
});
app.listen(4500, () => console.log('server started'));const express = require('express');
const app = express();
app.use('/user', (req, res, next) => {
req.userTime = new Date();
next();
});
app.listen(4500, () => console.log('server started'));Router-level middleware działa podobnie jak application-level middleware jedyna różnica jest taka iż ten rodzaj middleware działa w obrembie instancji express.Router().
const express = require('express');
const router = express.Router()
router.use((req, res, next) => {
console.log('current time', new Date());
next();
});
// ...Error-handling middleware obsługuje błędy oprogramowania. Ten rodzaj middleware przyjmuje cztery argumenty.
Definicja tego rodzaju middleware wygląda podobnie jak w przypadku wcześniejszych typów.
const express = require('express');
const app = express();
app.use((error, req, res, next) => {
console.error(error.message);
res.send(500, error.message);
});
// ...Built-in middleware czyli wbudowane w webframework Express oprogramowanie pośrednie.
Od wersji 4.x, Express udostępnia jedynie trzy wcześniej wymienione funkcje pośrednie.
Reszta middleware jest rozwijana w odzielnych modułach.
Third-party middleware czyli funkcje pośrednie stworzone przez innych poza zespołem twórców framework'a Express.
const express = require('express');
const bodyParser = require('body-parser'):
const app = express();
app.use(bodyParser.json());
// ...Express udostępnia mechanizm, który umożliwia korzystanie ze statycznych plików szablonów w aplikacji.
W środowisku wykonawczym silnik szablonów zastępuje zmienne w pliku statycznym, rzeczywistymi wartościami i przekształca szablon w plik HTML wysyłany do użytkownika.
Niektóre popularne silniki szablonów współpracują z Express'em(np. JADE/Pug, Mustache, EJS).
Express domyślnie używa JADE/Pug jako silnik szablonów.
Aby przerenderować pliki szablonów niezbędna jest odpowiednia konfiguracja:
// npm install pug
const express = require('express');
const app = express();
app.set('view engine', 'pug')
app.get('/', function (req, res) {
const scope = { title: 'some title', header: 'heloo!' };
res.render('index', scope);
});
// ...html
head
title= title
body
h1= header// npm install express-react-views react react-dom
const express = require('express');
const app = express();
const reactViews = require('express-react-views')
app.set('view engine', 'jsx');
app.engine('jsx', reactViews.createEngine());
app.get('/', function (req, res) {
const scope = { name: 'Jan' };
res.render('hello', scope);
});
app.listen(4500, () => console.log("server started"));const React = require('react');
const HelloMessage = (props) => (<div>Hello {props.name}</div>);
module.exports = HelloMessage;Obsługa błędów odnosi się do sposobu, w jaki framework Express przechwytuje i przetwarza błędy, które występują synchronicznie jaki i asynchronicznie.
Express sam w sobie zawiera domyślną procedurę obsługi błędów, więc jeżeli nie ma takiej potrzeby to nie trzeba jej pisać samodzielnie.
Ważne jest, aby program Express przechwytywał wszystkie błędy występujące podczas uruchamiania programów do obsługi tras jak i middleware.
Błędy występujące w kodzie synchronicznym wewnątrz procedur obsługi tras i oprogramowania pośredniego nie wymagają dodatkowej pracy. Jeśli kod synchroniczny zgłasza błąd, Express przechwytuje go i przetwarza.
const express = require('express');
const app = express();
app.get('/', function (req, res) {
throw new Error('some dumb error');
});
// ...W przypadku błędów zwracanych przez funkcje asynchroniczne wywoływane przez procedury obsługi i oprogramowanie pośrednie, należy przekazać je do funkcji next(), w której to Express je przechwyci i przetworzy.
const express = require('express');
const app = express();
app.get('/', function (req, res) {
setTimeout(() => {
const error = new Error('some dumb error');
next(error);
}, 5000);
});
// ...Express dostarcza wbudowaną obsługę błędów, która dba o wszelkie błędy, które mogą wystąpić w aplikacji.
Ta domyślna funkcja obsługi oprogramowania do obsługi błędów jest dodawana na KOŃCU stosu funkcji oprogramowania pośredniego.
Jeśli przekażemy błąd do funkcji next() i nie obsłużymy go w niestandardowej procedurze obsługi błędów, zostanie ona obsłużona przez wbudowany mechanizm obsługi błędów.
Konstrukcja middleware do obsługi błędów przyjmuje cztery argumenty, nie tak jak w przypadku zwykłych funkcji pośrednich. (err, req, res, next)
Middleware zawiązane z obsługą błędów muszą być użyte po dodaniu innych funkcji pośredniczących jak i obsługi ścieżek.
// ...
app.use(bodyParser.json());
app.use(cookieParser);
app.get('/', ...);
/// ...
app.use((error, req, res, next) => {
// ...
});
// ...