Interceptorer, tidsfrister og metadata
Legg til tverrgående autentisering og logging med interceptorer, samtidig som De håndhever tidsfrister og sender metadata.
Interceptorer, tidsfrister og metadata er en gratis leksjon i Bootcamp i backendutvikling med Node.js på CoddyKit. Dette er leksjon 3 av 4. Du kan lese hele leksjonen gratis nedenfor – og deretter øve praktisk i nettleseren med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i Bootcamp i backendutvikling med Node.js, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Bootcamp i backendutvikling med Node.js inneholder totalt 4 leksjoner.
Felles hensyn i gRPC
Når gRPC-tjenesten vokser, gjentar du den samme logikken i hver handler: autentisering, logging, tidsmåling og utforming av feil. Det er skjørt å kopiere dette inn i hver metode.
gRPC gir deg tre verktøy for å håndtere dette på en ryddig måte:
- Interceptorer — mellomvare som omslutter hvert kall, på klient- eller serversiden.
- Metadata — nøkkel/verdi-hoder som følger forespørselen, perfekt for autentiseringstokener og forespørsels-ID-er.
- Tidsfrister — et absolutt tidspunkt som et kall må være ferdig innen, og som videreføres mellom tjenester.
I denne leksjonen kobler vi alle tre sammen med @grpc/grpc-js i Node.js.
Hva metadata faktisk er
Metadata er en multimengde av strengnøkler med verdier som sendes med et gRPC-kall, omtrent som HTTP-hoder. Nøkler skiller ikke mellom store og små bokstaver. Verdiene er vanligvis ASCII-strenger; nøkler som slutter på -bin, inneholder binære Buffer-verdier.
På klienten legger du ved metadata; på serveren leser du den fra call-objektet. Bruk den til ting som ikke er en del av nyttelasten for virksomhetslogikken — autentiseringstokener, sporings-ID-er og lokalitet.
const grpc = require('@grpc/grpc-js');
// Build metadata on the client
const md = new grpc.Metadata();
md.set('authorization', 'Bearer abc123');
md.set('x-request-id', 'req-42');
// Reading is case-insensitive
console.log(md.get('Authorization')); // [ 'Bearer abc123' ]
console.log(md.get('x-request-id')); // [ 'req-42' ]Sende metadata med et unary-kall
Alle genererte klientmetoder godtar et valgfritt Metadata-argument før callbacken eller alternativene. Tokenet du angir her, kommer frem til serveren før handleren din kjøres.
Hold autentiseringshensyn utenfor protobuf-meldingene — legg tokenet i metadata, slik at den samme autentiseringslogikken fungerer for alle RPC-kall.
const grpc = require('@grpc/grpc-js');
function callWithAuth(client, token) {
const md = new grpc.Metadata();
md.set('authorization', 'Bearer ' + token);
client.GetUser({ id: '7' }, md, (err, res) => {
if (err) return console.error('RPC failed:', err.message);
console.log('User:', res);
});
}Lese metadata på serveren
På serveren eksponerer call-objektet metadata via call.metadata.get(key), som returnerer en array (en nøkkel kan forekomme flere ganger). Ved autentisering leser du authorization-headeren og validerer den før du gjør arbeid.
Hvis valideringen mislykkes, returnerer du en feil med grpc.status.UNAUTHENTICATED, slik at klientene kan reagere riktig.
const grpc = require('@grpc/grpc-js');
function getUser(call, callback) {
const auth = call.metadata.get('authorization')[0];
if (!auth || !auth.startsWith('Bearer ')) {
return callback({
code: grpc.status.UNAUTHENTICATED,
message: 'Missing or invalid token',
});
}
const token = auth.slice('Bearer '.length);
// ... verify token, then respond
callback(null, { id: call.request.id, name: 'Ada' });
}Serverinterceptorer: Ideen
Det er gjentakende arbeid å lese og validere tokener inne i hver handler. En serverinterceptor lar deg kjøre logikk én gang for alle RPC-kall.
I @grpc/grpc-js tilbys interceptorer på serversiden gjennom alternativet interceptors i server.addService (og via ServerInterceptingCall i nyere versjoner). Det klassiske, bredt støttede mønsteret er en klientinterceptor; på serveren omslutter mange team handlerne med en liten høyereordensfunksjon for autentisering og logging.
La oss begynne med dette mønsteret for innpakking av handlere — det er portabelt og enkelt å teste.
En autentiseringswrapper for handlere
En høyereordensfunksjon tar imot en handler og returnerer en ny handler som først kontrollerer autentisering og deretter delegerer. Dette er en ryddig måte å legge til et felles hensyn på, uten rammeverk.
Wrapperen avslutter med UNAUTHENTICATED når tokenet er ugyldig, og kaller ellers den opprinnelige handleren.
const grpc = require('@grpc/grpc-js');
function withAuth(handler) {
return (call, callback) => {
const auth = call.metadata.get('authorization')[0];
if (auth !== 'Bearer good-token') {
return callback({
code: grpc.status.UNAUTHENTICATED,
message: 'Unauthorized',
});
}
return handler(call, callback);
};
}
// Usage when registering the service:
// server.addService(svc, { GetUser: withAuth(getUser) });En loggingswrapper du kan sette sammen
Det samme mønsteret fungerer for logging og tidsmåling. Siden hver wrapper tar imot en handler og returnerer en handler, kan du sette dem sammen: withLogging(withAuth(getUser)).
Her registrerer loggeren metodeetiketten, ventetiden og forespørsels-ID-en fra metadata. Legg merke til at dette er et komplett, frittstående program som du kan kjøre for å se sammensetningen i praksis med et falskt call-objekt.
function withLogging(name, handler) {
return (call, callback) => {
const start = Date.now();
const reqId = call.metadata.reqId || 'none';
handler(call, (err, res) => {
const ms = Date.now() - start;
console.log(`[${name}] req=${reqId} ${err ? 'ERR' : 'OK'} ${ms}ms`);
callback(err, res);
});
};
}
function getUser(call, callback) {
callback(null, { id: call.request.id, name: 'Ada' });
}
const handler = withLogging('GetUser', getUser);
handler(
{ request: { id: '7' }, metadata: { reqId: 'req-42' } },
(err, res) => console.log('Response:', res)
);Klientinterceptorer
Det offisielle utvidelsespunktet på klienten er interceptoren: en funksjon som mottar options og en nextCall, og returnerer en InterceptingCall. Du overstyrer livssyklusmetoder som start for å legge inn metadata, eller onReceiveStatus for å observere resultater.
Nedenfor får alle utgående kall automatisk en authorization-header — den som utfører kallet, trenger aldri å huske den.
const grpc = require('@grpc/grpc-js');
function authInterceptor(token) {
return (options, nextCall) =>
new grpc.InterceptingCall(nextCall(options), {
start(metadata, listener, next) {
metadata.set('authorization', 'Bearer ' + token);
next(metadata, listener);
},
});
}
// const client = new UserService(addr, creds, {
// interceptors: [authInterceptor('abc123')],
// });Forstå tidsfrister
En tidsfrist er et absolutt tidspunkt som et kall må være ferdig innen. Det er IKKE en tidsavbruddsgrense per hopp — det er et tidspunkt på veggklokken som videreføres nedstrøms, slik at en kjede av tjenester deler ett samlet budsjett.
Angi den i kall-options som deadline: enten som en Date eller som millisekunder siden epoken. Det idiomatiske mønsteret er «nå pluss N ms».
- Hvis tidsfristen utløper, mislykkes kallet med
DEADLINE_EXCEEDED(status 4). - Servere kan kontrollere den gjenværende tiden og avslutte arbeidet tidlig.
const grpc = require('@grpc/grpc-js');
function callWithDeadline(client) {
const deadline = new Date(Date.now() + 2000); // 2s budget
client.GetUser({ id: '7' }, { deadline }, (err, res) => {
if (err && err.code === grpc.status.DEADLINE_EXCEEDED) {
return console.error('Timed out');
}
if (err) return console.error(err.message);
console.log(res);
});
}Tidsfrister på serversiden
Serveren mottar tidsfristen som call.getDeadline(). Før du starter kostbart arbeid, beregner du det gjenværende budsjettet og avbryter tidlig hvis det allerede er brukt opp — slik unngår du å sløse CPU på et kall klienten har gitt opp.
Når du sender forespørsler videre til nedstrøms tjenester, må du sende med den SAMME tidsfristen, slik at hele treet respekterer ett budsjett.
const grpc = require('@grpc/grpc-js');
function slowHandler(call, callback) {
const deadline = call.getDeadline(); // ms or Date
const remaining = Number(deadline) - Date.now();
if (remaining <= 0) {
return callback({ code: grpc.status.DEADLINE_EXCEEDED, message: 'No time left' });
}
// Forward the same deadline downstream:
// downstream.Fetch(req, { deadline }, cb);
callback(null, { ok: true, budgetMs: remaining });
}Slik henger det sammen: en pipeline med budsjett
Her er tankemodellen for én forespørsel: Klienten setter en tidsfrist og autentiseringsmetadata. En klientinterceptor legger inn tokenet; kallet inneholder en forespørsels-ID. På serveren validerer en autentiseringswrapper tokenet, en loggingswrapper måler tiden, og handlerne kontrollerer den gjenværende tidsfristen før de sender forespørsler videre — og viderefører både metadata og tidsfristen nedstrøms.
Denne frittstående simuleringen viser hele kjeden av wrappere og en kontroll av tidsfristen uten noen server, slik at du kan kjøre den direkte.
function withAuth(h) {
return (call, cb) =>
call.metadata.authorization === 'Bearer good'
? h(call, cb)
: cb({ code: 16, message: 'UNAUTHENTICATED' });
}
function withDeadline(h) {
return (call, cb) =>
call.deadline - Date.now() <= 0
? cb({ code: 4, message: 'DEADLINE_EXCEEDED' })
: h(call, cb);
}
function getUser(call, cb) {
cb(null, { id: call.request.id, name: 'Ada' });
}
const pipeline = withAuth(withDeadline(getUser));
const call = {
request: { id: '7' },
metadata: { authorization: 'Bearer good' },
deadline: Date.now() + 1000,
};
pipeline(call, (err, res) =>
console.log(err ? 'Error ' + err.code : 'OK', res || '')
);Kort kontroll
En klient setter deadline = Date.now() + 3000 og kaller tjeneste A, som deretter kaller tjeneste B. Hva er riktig oppførsel for tidsfristen?
Oppsummering
Du har nå verktøyene du trenger for gRPC-kall i produksjonskvalitet:
- Metadata inneholder data utenfor nyttelasten, som
authorizationogx-request-id; les den på serversiden medcall.metadata.get(key)(returnerer en array, og nøkler skiller ikke mellom store og små bokstaver). - Interceptorer sentraliserer felles logikk: klientinterceptorer bruker
InterceptingCalltil å legge inn metadata istart; på serveren legger sammensettbare handlerwrappere til autentisering og logging én gang. - Tidsfrister er absolutte tidspunkter som angis via kall-
options.deadlineog videreføres uendret nedstrøms, slik at en hel kjede deler ett budsjett; overskridelse girDEADLINE_EXCEEDED(status 4).
Kombiner dem: legg inn autentisering og forespørsels-ID via en interceptor, pakk inn handlere for autentisering og logging, og send alltid tidsfristen videre når du fordeler arbeidet til andre tjenester.
Lær deg JavaScript med en AI-veileder – gratis
Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.
- Kurs
- 22
- Leksjoner
- 92
Ofte stilte spørsmål
Er leksjonen «Interceptorer, tidsfrister og metadata» gratis?
Ja – hele teksten i «Interceptorer, tidsfrister og metadata» er gratis å lese her på nettet. For å øve interaktivt med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt, og for å låse opp resten av Bootcamp i backendutvikling med Node.js-kurset, kan du oppgradere til CoddyKit PRO. Kurset i Bootcamp i backendutvikling med Node.js inneholder totalt 4 leksjoner.
Hva lærer jeg i «Interceptorer, tidsfrister og metadata»?
Legg til tverrgående autentisering og logging med interceptorer, samtidig som De håndhever tidsfrister og sender metadata. Du øver på Bootcamp i backendutvikling med Node.js med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.
Trenger jeg erfaring for å begynne med Bootcamp i backendutvikling med Node.js?
Ingen tidligere erfaring er nødvendig. Bootcamp i backendutvikling med Node.js på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 3 av 4.
Hvor lang tid tar leksjonen «Interceptorer, tidsfrister og metadata»?
De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.
Kan jeg skrive og kjøre kode i denne Bootcamp i backendutvikling med Node.js-leksjonen?
Ja. Alle Bootcamp i backendutvikling med Node.js-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.
Alle leksjonene i dette kurset
- Definering av tjenester og meldinger med Protobuf IDL
- Unary-, server-, klient- og toveisstrømmende RPC-er
- Interceptorer, tidsfrister og metadata
- Proto-evolusjon og bakoverkompatibilitet