Middleware

Middleware

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

ExpressJS - Middleware

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.

ExpressJS - Middleware

Funkcje middleware mogą wykonywać następujące zadania:

  • wykonać dowolny kod
  • wprowadzić zmiany w obiektach żądań i odpowiedzi
  • zakończyć żadanie
  • wywołac następne oprogramowanie pośrednie w stosie

Konstrukcja middleware

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'));

Zapamiętać!

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.

Przykład

// ...
const timeMiddleware = (req, res, next) => {
    req.requestTime = new Date();
    next();
};

app.use(timeMiddleware);

app.get('/', (req, res) => {
    res.send('request time: ' + req.requestTime);
});
// ...

Typy middleware

W Express możemy wykorzystać takie typy middleware jak:

APPLICATION-LEVEL MIDDLEWARE

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.

Przykład

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'));

Przykład ze ścieżką

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

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().

Przykład

const express = require('express');
const router = express.Router()

router.use((req, res, next) => {
    console.log('current time', new Date());
    next();
});
// ...

ERROR-HANDLING MIDDLEWARE

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. 

Przykład

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

Built-in middleware czyli wbudowane w webframework Express oprogramowanie pośrednie.

  • express.static - middleware odpowiedzialny za udostępnianie statycznych zasobów
  • express.json - parsowanie zawartości przychodzącego z żądania typu JSON
  • express.urlencoded - parsowanie zawartości przychodzącego z żądania z formularza

BUILT-IN MIDDLEWARE

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

Third-party middleware czyli funkcje pośrednie stworzone przez innych poza zespołem twórców framework'a Express.

Przykład

const express = require('express');
const bodyParser = require('body-parser'):
const app = express();

app.use(bodyParser.json());

// ...

Template

Template

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.

Template engines

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.

Render

Aby przerenderować pliki szablonów niezbędna jest odpowiednia konfiguracja:

  • ustawić ścieżkę do katalogu gdzie będą znajdować sie szablony, np: app.set('views', './templates');
  • ustawić odpowiedni silinik szablonów, np: app.set('view engine', 'pug') oraz pobrać odpowiednią paczkę z npm

Przykład

// 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);
});
// ...

PUG template

html
    head
        title= title
    body
        h1= header

Przykład (react)

// 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"));

views/hello.jsx

const React = require('react');

const HelloMessage = (props) => (<div>Hello {props.name}</div>);

module.exports = HelloMessage;

Error handling

Error handling

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.

Catching errors

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.

Przykład synchroniczny

const express = require('express');
const app = express();

app.get('/', function (req, res) {
    throw new Error('some dumb error');
});
// ...

Catching errors

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.

Przykład asynchroniczny

const express = require('express');
const app = express();

app.get('/', function (req, res) {
    setTimeout(() => {
        const error = new Error('some dumb error');
        next(error);
    }, 5000);
});
// ...

Default error handler

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.

Default error handler

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.

Error handlers

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.

Przykład

// ...
app.use(bodyParser.json());
app.use(cookieParser);

app.get('/', ...);
/// ...

app.use((error, req, res, next) => {
    // ...
});
// ...
Made with Slides.com