javascript - Sende variabler til neste middleware ved bruk av next() i Express.js
Jeg vil sende en variabel fra den første mellomvaren til en annen mellomvare, og jeg prøvde å gjøre dette, men det var «req.somevariable er gitt som 'undefined'».
//app.js
..
app.get('/someurl/', middleware1, middleware2)
...
////middleware1
...
some conditions
...
res.somevariable = variable1;
next();
...
////middleware2
...
some conditions
...
variable = req.somevariable;
...
Svar #1
v4.x API-dokumentasjon
Dette er hva res.locals-objektet er til for. Å sette variabler direkte på request-objektet støttes ikke eller er dokumentert. res.locals er garantert å beholde tilstanden gjennom hele livet til en request.
Sitat fra dokumentasjonen:
Bruk denne egenskapen for å sette variabler som er tilgjengelige i maler gjengitt med res.render. Variablene som settes på res.locals er tilgjengelige innenfor en enkelt forespørsel-svar-syklus, og vil ikke bli delt mellom forespørsler.
Det lokale objektet brukes av visningsmotorer for å gjengi et svar. Objektets nøkler kan være spesielt sensitive og bør ikke inneholde brukerstyrt input, da det kan påvirke driften av visningsmotoren eller gi en vei til cross-site scripting. Konsulter dokumentasjonen for den brukte visningsmotoren for ytterligere hensyn.
app.use(function(req, res, next) {
res.locals.user = req.user;
res.locals.authenticated = !req.user.anonymous;
next();
});
For å hente variabelen i neste mellomvare:
app.use(function(req, res, next) {
if (res.locals.authenticated) {
console.log(res.locals.user.id);
}
next();
});
Svar #2
Fest variabelen din til res.locals-objektet, ikke req.
I stedet for
req.somevariable = variable1;
Ha :
res.locals.somevariable = variable1;
Som andre har påpekt, er res.locals den anbefalte måten å sende data gjennom middleware på.
Svar #3
Jeg tror ikke at beste praksis vil være å sende en variabel som req.YOUR_VAR. Du kan vurdere req.YOUR_APP_NAME.YOUR_VAR eller req.mw_params.YOUR_VAR.
Det vil hjelpe deg med å unngå å overskrive andre attributter.
Svar #4
Det vanligste mønsteret for å sende variabler videre til annen middleware og endepunktfunksjoner er å legge verdier til forespørselsobjektet req.
I ditt tilfelle vil det bety å ha mellomvare som disse:
app.use(function (req, res, next) {
req.someVariable = 123;
next();
});
app.use(function (req, res, next) {
console.log("The variable is", req.someVariable);
next();
});
Det finnes mange vanlige bruksområder for dette mønsteret, og det er den standardmåten å gjøre det på i Express-miljøet. Se for eksempel:
- express.json, som følger med express, var tidligere en del av body-parser som følger det samme mønsteret for all forespørselsparsing.
- multer brukt for parsing av multipart-data
- express-jwt
- express-validator (se kode)
- express-økt
- express-brukeragent
- express-pino-logger
- express-bunyan-logger
Det er verdt å merke seg at det for øyeblikket høyest rangerte svaret feilaktig anbefaler å bruke res.locals til dette formålet - noe som ser ut til å stamme fra en feillesning av dokumentasjonen. Av den grunn vil jeg forklare hvorfor dette ikke er den vanlige tilnærmingen til problemet (selv om det heller ikke er særlig skadelig).
Dokumentasjonen
Som støttende bevis for at res.locals-tilnærmingen er den riktige i dette tilfellet, blir den nå foreldede dokumentasjonen sitert:
Et objekt som inneholder responslokale variabler som er avgrenset til forespørselen, og derfor kun er tilgjengelige for visningen(e) som renderes under den forespørsel-/responssyklusen (hvis noen). Ellers er denne egenskapen identisk med app.locals.
Denne egenskapen er nyttig for å eksponere informasjon på forespørselsnivå, slik som forespørselens sti, autentisert bruker, brukerinnstillinger, og så videre.
Legg merke til innrammingen her: res.locals er for variabler som kun er tilgjengelige «for de visningene som rendres under den forespørselen» (utheving lagt til).
Det er det res.locals refererer til. res.render renderer en malfil med noen gitte data i tillegg til tilgang til locals. Dette var faktisk klarere i v2-dokumentasjonen, og vi har nå oppdatert den nåværende Express-dokumentasjonen for å være tydeligere:
Bruk denne egenskapen for å sette variabler som er tilgjengelige i maler gjengitt med res.render. Variablene som settes på res.locals er tilgjengelige innenfor en enkelt forespørsel-svar-syklus, og vil ikke bli delt mellom forespørsler.
For å beholde lokale variabler for bruk i malgjenngivelse mellom forespørsler, bruk i stedet app.locals.
Denne egenskapen er nyttig for å eksponere forespørselsnivåinformasjon som forespørselsbanenavn, autentisert bruker, brukerinnstillinger og så videre til maler som rendres innenfor applikasjonen.
(Utheving lagt til.)
Guiden
Ytterligere bevis på at utvidelse av req er den standard tilnærmingen finnes i guiden om Writing Middleware, som sier:
Deretter vil vi lage en mellomvarefunksjon kalt «requestTime» og legge til en egenskap kalt requestTime på forespørselobjektet.
const requestTime = function (req, res, next) { req.requestTime = Date.now() next() }
Når dette ble nevnt i diskusjonen i svarene på dette spørsmålet her, svarte en bruker: «Dette var måten du ville gjort det på før de la til res.locals, så det kan være gamle dokumenter. res.locals er et navnerom spesifikt for dette.»
Dette stemmer imidlertid ikke overens med historien til kodebasen: locals har eksistert siden v2, som er betydelig tidligere enn f.eks. express.json ble inkludert i biblioteket, på det tidspunktet ville det ha vært fornuftig å endre oppførselen, hvis det faktisk var korrekt å lagre verdier i res.locals.
Avsluttende merknader
Shoutout til @real_ate som skrev i kommentarene, men ble oversett.
