Egendefinerte mellomvarekjeder
Bygg egendefinert mellomvare for logging, hastighetsbegrensning eller autorisasjon, og kjed dem sammen.
Egendefinerte mellomvarekjeder er en gratis leksjon i Typesikre API-er fra frontend til backend med tRPC på CoddyKit. Dette er leksjon 3 av 4. Du kan lese valgfritt 3 leksjoner fra denne læringsstien gratis i sin helhet – deretter låser CoddyKit PRO opp alle leksjoner, samt praktisk øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i Typesikre API-er fra frontend til backend med tRPC, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Typesikre API-er fra frontend til backend med tRPC inneholder totalt 4 leksjoner.
Lenke sammen flere middleware-komponenter
I tRPC lar middleware deg kjøre logikk før prosedyren utføres. Hva om du trenger flere kontroller, som logging, autentisering og validering, for ett enkelt API-kall?
Det er her middleware-kjeder kommer til nytte! De lar deg stable flere middleware-funksjoner, som utføres én etter én.
Fordeler ved å lenke sammen middleware
Det gir flere fordeler å lenke sammen middleware-komponenter:
- Modularitet: Hver middleware-komponent fokuserer på ett enkelt ansvarsområde, for eksempel logging eller autentisering.
- Gjenbruk: Opprett generell middleware som kan brukes på ulike prosedyrer eller rutere.
- Utførelsesrekkefølge: Styr den nøyaktige rekkefølgen på operasjonene før hovedlogikken i prosedyren kjøres.
- Tidlig avslutning: En middleware-komponent kan stoppe kjeden tidlig hvis en betingelse ikke er oppfylt, for eksempel ved uautorisert tilgang.
Slik fungerer `next()`
Husk at tRPC-middleware mottar en next-funksjon. Når du kaller next(), overlater du kontrollen til neste middleware-komponent i kjeden, eller til den faktiske prosedyrehåndtereren hvis dette er den siste middleware-komponenten.
Hvis en middleware-komponent ikke kaller next(), stopper kjeden, og prosedyrehåndtereren blir ikke kjørt. Dette er avgjørende for kontroller som autentisering!
Først: Logging-middleware
La oss opprette en enkel logging-middleware. Den skal logge når en forespørsel starter, og hvor lang tid den tok. Dette er et vanlig mønster for overvåking.
Legg merke til at next() awaites for å sikre at prosedyren (og påfølgende middleware-komponenter) er ferdig før varigheten logges.
type Context = { userId: string | null };
const trpc = {
middleware: (handler: any) => handler,
procedure: {
use: (mw: any) => ({
query: (f: any) => f,
mutation: (f: any) => f
}),
query: (f: any) => f,
mutation: (f: any) => f
},
router: (cfg: any) => cfg,
};
const logMiddleware = trpc.middleware(async ({ path, type, next }) => {
console.log(`[${type}] Request to ${path} started.`);
const start = Date.now();
const result = await next();
const durationMs = Date.now() - start;
console.log(`[${type}] Request to ${path} finished in ${durationMs}ms.`);
return result;
});
const appRouter = trpc.router({
example: trpc.procedure
.use(logMiddleware)
.query(() => "Data fetched!")
});Deretter: Autentiserings-middleware
Deretter bygger vi en autentiserings-middleware. Denne middleware-komponenten kontrollerer om en bruker er logget inn, altså om ctx.userId finnes. Hvis ikke, kaster den en feil og stopper dermed prosedyren.
Husk at ctx-objektet (konteksten) sendes til middleware-komponenter, slik at de får tilgang til forespørselsspesifikke data.
type Context = { userId: string | null };
const trpc = {
middleware: (handler: any) => handler,
procedure: {
use: (mw: any) => ({
query: (f: any) => f,
mutation: (f: any) => f
}),
query: (f: any) => f,
mutation: (f: any) => f
},
router: (cfg: any) => cfg,
};
const isAuthenticated = trpc.middleware(async ({ ctx, next }) => {
if (!ctx.userId) {
throw new Error("UNAUTHORIZED: Please log in.");
}
return next();
});
const appRouter = trpc.router({
protected: trpc.procedure
.use(isAuthenticated)
.query(({ ctx }) => `Welcome, user ${ctx.userId}!`)
});Bygge en middleware-kjede
Nå kombinerer vi logMiddleware og isAuthenticated-middleware. Rekkefølgen er viktig: Logging skal skje først, deretter autentisering.
Vi bruker ganske enkelt .use() flere ganger. tRPC utfører dem i den rekkefølgen de er definert.
type Context = { userId: string | null };
const trpc = {
middleware: (handler: any) => handler,
procedure: {
use: (mw: any) => ({
query: (f: any) => f,
mutation: (f: any) => f
}),
query: (f: any) => f,
mutation: (f: any) => f
},
router: (cfg: any) => cfg,
};
const logMiddleware = trpc.middleware(async ({ path, type, next }) => {
console.log(`[${type}] Request to ${path} started.`);
const start = Date.now();
const result = await next();
const durationMs = Date.now() - start;
console.log(`[${type}] Request to ${path} finished in ${durationMs}ms.`);
return result;
});
const isAuthenticated = trpc.middleware(async ({ ctx, next }) => {
if (!ctx.userId) {
throw new Error("UNAUTHORIZED: Please log in.");
}
return next();
});
const appRouter = trpc.router({
protectedData: trpc.procedure
.use(logMiddleware)
.use(isAuthenticated)
.query(({ ctx }) => `Secret data for ${ctx.userId}!`)
});Utførelsesrekkefølge
Når en forespørsel treffer protectedData:
logMiddlewarekjører først.- Hvis
logMiddlewarekallernext(), kjører deretterisAuthenticated. - Hvis
isAuthenticatedkallernext(), kjører den faktiskequery-prosedyrehåndtereren. - Hvis en middleware-komponent kaster en feil, som
isAuthenticatedkan gjøre, stopper kjeden umiddelbart, og feilen returneres.
Dynamisk middleware
Hva om du trenger ulike autoriseringsnivåer? Du kan opprette en funksjon som returnerer en middleware-komponent, slik at konfigurasjonen kan være dynamisk.
Dette mønsteret kalles en middleware-bygger og er nyttig når du skal opprette fleksibel og gjenbrukbar middleware.
type Context = { userId: string | null; userRole: string | null };
const trpc = {
middleware: (handler: any) => handler,
procedure: {
use: (mw: any) => ({
query: (f: any) => f,
mutation: (f: any) => f
}),
query: (f: any) => f,
mutation: (f: any) => f
},
router: (cfg: any) => cfg,
};
const hasRole = (requiredRole: string) => {
return trpc.middleware(async ({ ctx, next }) => {
if (!ctx.userRole || ctx.userRole !== requiredRole) {
throw new Error(`FORBIDDEN: ${requiredRole} role required.`);
}
return next();
});
};
const appRouter = trpc.router({
adminPanel: trpc.procedure
.use(hasRole("admin"))
.query(() => "Welcome, admin!")
});Lenke sammen dynamisk middleware
Du kan kombinere statisk middleware, som loggeren vår, med dynamiske middleware-byggere, som rolleoppslaget vårt, i den samme kjeden.
Dette gir svært fleksible og sikre API-endepunkter, der spesifikk logikk kan brukes basert på konfigurasjon eller verdier fra kjøring.
type Context = { userId: string | null; userRole: string | null };
const trpc = {
middleware: (handler: any) => handler,
procedure: {
use: (mw: any) => ({
query: (f: any) => f,
mutation: (f: any) => f
}),
query: (f: any) => f,
mutation: (f: any) => f
},
router: (cfg: any) => cfg,
};
const logMiddleware = trpc.middleware(async ({ path, type, next }) => {
console.log(`[${type}] Request to ${path} started.`);
const start = Date.now();
const result = await next();
const durationMs = Date.now() - start;
console.log(`[${type}] Request to ${path} finished in ${durationMs}ms.`);
return result;
});
const hasRole = (requiredRole: string) => {
return trpc.middleware(async ({ ctx, next }) => {
if (!ctx.userRole || ctx.userRole !== requiredRole) {
throw new Error(`FORBIDDEN: ${requiredRole} role required.`);
}
return next();
});
};
const appRouter = trpc.router({
adminReport: trpc.procedure
.use(logMiddleware)
.use(hasRole("admin"))
.query(() => "Sensitive admin report data.")
});Logikk i middleware-kjeder
Se på følgende definisjon av en tRPC-prosedyre:
// Assume logMiddleware and authMiddleware are defined
// authMiddleware throws if ctx.userId is null
// logMiddleware always calls next()
const myProcedure = trpc.procedure
.use(logMiddleware)
.use(authMiddleware)
.query(({ ctx }) => `Hello ${ctx.userId}`);Hvis en forespørsel kommer inn med ctx.userId = null, hva skjer da?
Oppsummering av middleware-kjeder
Godt jobbet! Du har lært hvordan du bygger og lenker sammen flere egendefinerte middleware-komponenter i tRPC.
- Middleware-kjeder lar deg bruke flere lag med logikk, som logging, autentisering og validering, før en prosedyre utføres.
- Metoden
.use()brukes til å legge til middleware-komponenter, og de kjøres i den rekkefølgen de er definert. - Funksjonen
next()er avgjørende for å føre kontrollen videre i kjeden. - Middleware-byggere kan opprette dynamisk og konfigurerbar middleware som gir bedre gjenbruk.
Dette kraftige mønsteret bidrar til å holde tRPC API-koden ryddig, modulær og robust!
Lær deg Typesikre API-er fra frontend til backend med tRPC 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
- 10
- Leksjoner
- 40
Ofte stilte spørsmål
Er leksjonen «Egendefinerte mellomvarekjeder» gratis?
Ja – du kan lese valgfritt 3 av leksjonene i læringsstien Typesikre API-er fra frontend til backend med tRPC, inkludert «Egendefinerte mellomvarekjeder», gratis i sin helhet her på nettet. Deretter låser CoddyKit PRO opp alle leksjoner, samt interaktiv øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Kurset i Typesikre API-er fra frontend til backend med tRPC inneholder totalt 4 leksjoner.
Hva lærer jeg i «Egendefinerte mellomvarekjeder»?
Bygg egendefinert mellomvare for logging, hastighetsbegrensning eller autorisasjon, og kjed dem sammen. Du øver på Typesikre API-er fra frontend til backend med tRPC 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 Typesikre API-er fra frontend til backend med tRPC?
Ingen tidligere erfaring er nødvendig. Typesikre API-er fra frontend til backend med tRPC 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 «Egendefinerte mellomvarekjeder»?
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 Typesikre API-er fra frontend til backend med tRPC-leksjonen?
Ja. Alle Typesikre API-er fra frontend til backend med tRPC-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
- Opprette tRPC-kontekst
- Autentiseringsmellomvare
- Egendefinerte mellomvarekjeder
- Middleware for logging og ytelsesmåling