DENO本機HTTP服務器DeNo部署的中間件框架,Node.js 16.5及以後的Cloudflare工人和BUN。它還包括一個中間件路由器。
此中間件框架的靈感來自KOA和中間件路由器,靈感來自 @koa/路由器。
此讀數重點關注橡木API的機制,適用於熟悉JavaScript中間件框架(如Express和Koa)以及對DeNo的體面理解的人。如果您不熟悉這些,請在oakserver.github.io/oak上查看文檔。
另外,請查看我們的常見問題解答和社區資源的令人敬畏的網站。
筆記
此讀數中的示例從main拉動,是為DeNo CLI或DeNo部署而設計的,當您想實際部署工作負載時,這可能是沒有意義的。您可能需要將“ PIN”“ PIN”與特定版本兼容,該版本與您正在使用的DeNo版本兼容,並且具有您期望的固定API。 https://deno.land/x/支持在URL中使用git標籤來指導您以特定版本為單位。因此,要使用Oak的13.0.0版本,您將要導入https://deno.land/x/[email protected]/mod.ts 。
橡木可在deno.land/x和JSR上使用。要使用deno.land/x ,導入到一個模塊中:
import { Application } from "https://deno.land/x/oak/mod.ts" ;要從JSR使用,將導入到一個模塊中:
import { Application } from "jsr:@oak/oak@14" ;橡木可用於NPM和JSR上的Node.js。要從NPM使用,請安裝軟件包:
npm i @oakserver/oak@14
然後導入一個模塊:
import { Application } from "@oakserver/oak" ;要從JSR使用,請安裝軟件包:
npx jsr i @oak/oak@14
然後導入一個模塊:
import { Application } from "@oak/oak/application" ; 筆記
當前不支持發送,Websocket升級和在TLS/HTTP上服務。
此外,Cloudflare Worker環境和執行上下文當前尚未暴露於中間件。
橡木可用於JSR的Cloudflare工人。要將包裹添加到您的CloudFlare Worker項目中:
npx jsr add @oak/oak@14
然後導入一個模塊:
import { Application } from "@oak/oak/application" ;與其他運行時間不同,OAK應用程序不收聽傳入的請求,而是處理Worker提取請求。最小的示例服務器將是:
import { Application } from "@oak/oak/application" ;
const app = new Application ( ) ;
app . use ( ( ctx ) => {
ctx . response . body = "Hello CFW!" ;
} ) ;
export default { fetch : app . fetch } ; 筆記
當前不支持發送和Websocket升級。
橡木可用於JSR上的BUN。使用安裝軟件包:
bunx jsr i @oak/oak@14
然後導入一個模塊:
import { Application } from "@oak/oak/application" ; 筆記
當前不支持發送和Websocket升級。
Application程序類協調管理HTTP服務器,運行中間件以及處理請求時發生的錯誤。通常使用兩個方法: .use()和.listen() 。通過.use()方法添加了中間件,並且.listen()方法將啟動服務器,並使用註冊的中間件開始處理請求。
基本用法,對Hello World響應每個請求! :
import { Application } from "jsr:@oak/oak/application" ;
const app = new Application ( ) ;
app . use ( ( ctx ) => {
ctx . response . body = "Hello World!" ;
} ) ;
await app . listen ( { port : 8000 } ) ;然後,您將在DeNo中運行此腳本,例如:
> deno run --allow-net helloWorld.ts
有關DENO下運行代碼的更多信息,或有關如何安裝DENO CLI的信息,請查看DENO手冊。
中間軟件作為堆棧處理,每個中間件功能都可以控制響應的流程。當調用中間軟件時,將其傳遞給堆棧中的“下一個”方法的上下文。
一個更複雜的例子:
import { Application } from "jsr:@oak/oak/application" ;
const app = new Application ( ) ;
// Logger
app . use ( async ( ctx , next ) => {
await next ( ) ;
const rt = ctx . response . headers . get ( "X-Response-Time" ) ;
console . log ( ` ${ ctx . request . method } ${ ctx . request . url } - ${ rt } ` ) ;
} ) ;
// Timing
app . use ( async ( ctx , next ) => {
const start = Date . now ( ) ;
await next ( ) ;
const ms = Date . now ( ) - start ;
ctx . response . headers . set ( "X-Response-Time" , ` ${ ms } ms` ) ;
} ) ;
// Hello World!
app . use ( ( ctx ) => {
ctx . response . body = "Hello World!" ;
} ) ;
await app . listen ( { port : 8000 } ) ;要提供HTTPS服務器,然後app.listen()選項需要包括設置為true選項.secure選項並提供.certFile和.keyFile選項。
.handle()方法.handle()方法用於處理請求並接收響應,而無需讓應用程序管理服務器方面。這是高級用法,大多數用戶都希望使用.listen() 。
.handle()方法最多接受三個參數。第一個是Request參數,第二個是Deno.Conn參數。第三個可選參數是指示該請求是否是“安全”的標誌,其源於與遠程客戶端的TLS連接。如果ctx.respond === true則使用Response對像或undefined方法解決該方法。
一個例子:
import { Application } from "jsr:@oak/oak/application" ;
const app = new Application ( ) ;
app . use ( ( ctx ) => {
ctx . response . body = "Hello World!" ;
} ) ;
const listener = Deno . listen ( { hostname : "localhost" , port : 8000 } ) ;
for await ( const conn of listener ) {
( async ( ) => {
const requests = Deno . serveHttp ( conn ) ;
for await ( const { request , respondWith } of requests ) {
const response = await app . handle ( request , conn ) ;
if ( response ) {
respondWith ( response ) ;
}
}
} ) ;
}應用程序實例也具有一些屬性:
contextState - 確定用於創建新上下文狀態的方法。 "clone"的值將把狀態設置為應用程序狀態的克隆。 "prototype"的值意味著該應用程序的狀態將用作上下文狀態的原型。 "alias"的值表示應用程序的狀態和上下文狀態將是對同一對象的引用。 "empty"的值將用一個空對像初始化上下文的狀態。
.jsonBodyReplacer可選的替換函數,在形成響應時將應用於JSON體。
.jsonBodyReviver可選的reviver函數,在請求中讀取JSON主體時將應用。
.keys
簽名和驗證cookie時要使用的鍵。該值可以設置為一個鍵和KeyStack的實例,或提供與KeyStack相同接口的對象(例如KeyGrip的實例)。如果僅通過鍵,OAK將通過KeyStack進行管理鍵,該鍵可以輕鬆旋轉,而無需重新簽名數據值。
.proxy
默認為false ,但可以通過Application構造函數選項設置。這旨在表明該應用程序是代理後面的,並且將在處理請求時使用X-Forwarded-Proto , X-Forwarded-Host和X-Forwarded-For ,這應該提供有關請求的更準確的信息。
.state
應用程序狀態的記錄,可以通過在構造Application()時指定通用參數或通過傳遞狀態對象(例如Application({ state }) )來強烈鍵入。
傳遞給中間件的上下文具有多個屬性:
.app
對正在調用此中間件的Application的引用。
.cookies
此上下文的Cookies實例,該實例使您可以閱讀和設置cookie。
.request
包含有關請求的詳細信息的Request對象。
.respond
確定中間件是否完成處理時,應用程序應將.response發送給客戶端。如果是true ,則將發送響應,如果false則不會發送響應。默認值為true ,但是某些方法,例如.upgrade()和.sendEvents()會將其設置為false 。
.response
將用於形成發送給請求者的響應Response對象。
.socket
如果連接尚未升級到Web插座,則將undefined 。如果連接已升級,則將設置.socket接口。
.state
應用程序狀態的記錄,可以通過在構造Application()時指定通用參數或通過傳遞狀態對象(例如Application({ state }) )來強烈鍵入。
傳遞給中間件的上下文有一些方法:
.assert()
提出一個斷言,如果不是真的,就會拋出一個由第二個參數識別的子類的HTTPError ,而消息是第三個參數。
.send()
將文件流向請求客戶端。有關更多信息,請參見下面的靜態內容。
.sendEvents()
將當前連接轉換為服務器量事件響應,然後返回ServerSentEventTarget ,可以將消息和事件流傳輸到客戶端。這將.respond為false 。
.throw()
拋出HTTPError ,該子類由第一個參數識別,消息傳遞為第二個。
.upgrade()
嘗試將連接升級到Web套接字連接,然後返回WebSocket接口。以前的Oak版本,這將是通過std/ws Web套接字解決的Promise 。
與其他中間件框架不同, context沒有大量的別名。有關請求的信息僅位於.request中,有關響應的信息僅位於.response中。
context.cookies允許訪問請求中的cookie值,並允許在響應中設置cookie。如果在應用程序上設置了.keys屬性,它將自動確保cookie。因為.cookies使用Web Crypto API簽名和驗證cookie,並且這些API以異步方式工作,所以Cookie API以異步方式工作。它有幾種方法:
.get(key: string, options?: CookieGetOptions): Promise<string | undefined>
嘗試從請求中檢索cookie並根據密鑰返回cookie的值。如果設置了應用程序.keys ,則將使用cookie的cookie驗證cookie。如果cookie有效,則承諾將以該值解決。如果它無效,則將在響應中刪除cookie簽名。如果cookie沒有由當前密鑰簽署,則將辭職並添加到響應中。
.set(key: string, value: string, options?: CookieSetDeleteOptions): Promise<void>
將根據提供的密鑰,值和任何選項在響應中設置cookie。如果設置了應用程序.keys ,則將簽署cookie,並將簽名添加到響應中。當鍵異步簽名時,建議.set()方法。
context.request包含有關請求的信息。它包含幾個屬性:
.body
提供對請求主體的訪問的對象。有關請求主體API的詳細信息,請參見下文。
.hasBody
如果請求可能有一個主體,則設置為true ,或者如果不為false 。不過,它無法驗證身體是否由內置的身體解析器支撐。
[!警告]這是一個不可靠的API。在許多情況下,在HTTP/2中,由於HTTP/2的流性質,除非您嘗試閱讀身體,否則您無法確定請求是否具有身體。從DENO 1.16.1開始,對於HTTP/1.1,DENO也反映了這種行為。確定請求是否具有身體的唯一可靠方法是嘗試閱讀身體。
最好通過給定方法確定身體是否對您有意義,然後嘗試在給定的上下文中讀取和處理身體。例如, GET和HEAD絕不能具有身體,但是諸如DELETE和OPTIONS類的方法可能具有身體,並且如果對您的應用有意義,則應進行有條件處理的身體。
.headers
請求的標題, Headers的實例。
.method
代表請求的HTTP方法的字符串。
.originalRequest
棄用這將在以後的Oak發行中刪除。
“ RAW” NativeServer RESICT,這是DOM Request對象的抽象。 .originalRequest.request是正在處理的DOM Request實例。用戶通常應避免使用這些。
.secure
一個適用於.protocol的快捷方式,如果https否則為false則返回true 。
.source
在DENO下運行時, .source將設置為源Web標準Request 。在nodejs下運行時,這將是undefined 。
.url
一個基於請求的完整URL的URL實例。這代替了在請求對象的其餘部分中暴露於URL的一部分。
和幾種方法:
.accepts(...types: string[])
協商響應請求支持的內容類型。如果沒有傳遞內容類型,該方法將返回接受的內容類型的優先數組。如果傳遞了內容類型,則返回最佳協商內容類型。如果沒有內容類型匹配undefined返回。
.acceptsEncodings(...encodings: string[])
協商響應請求支持的編碼內容。如果沒有傳遞編碼,則該方法將返回優先的接受編碼數組。如果傳遞編碼,則返回最好的協商編碼。如果沒有編碼匹配,則返回undefined 。
.acceptsLanguages(...languages: string[])
談判客戶能夠理解的語言。該區域變體偏愛的地方。如果沒有傳遞編碼,則該方法將返回優先理解的語言數組。如果通過語言,則返回最好的談判語言。如果沒有語言匹配undefined語言,則將返回。
重要的
該API在橡木V13和更高版本中發生了很大變化。自橡木於2018年創建以來,以前的API已經有機地生長,並且沒有代表任何其他常見的API。 V13中引入的API與Fetch API的Request方式更好地保持一致,並且對於第一次來橡樹的開發人員應該更熟悉。
OAK請求的.body的靈感來自Fetch API的Request ,但有一些添加功能。上下文的request.body是一個提供多個屬性的對象的實例:
.has
如果請求可能有一個主體,則設置為true ,或者如果不為false 。不過,它無法驗證身體是否由內置的身體解析器支撐。
[!重要]這是一個不可靠的API。在許多情況下,在HTTP/2中,由於HTTP/2的流性質,除非您嘗試閱讀身體,否則您無法確定請求是否具有身體。從DENO 1.16.1開始,對於HTTP/1.1,DENO也反映了這種行為。確定請求是否具有身體的唯一可靠方法是嘗試閱讀身體。
最好通過給定方法確定身體是否對您有意義,然後嘗試在給定的上下文中讀取和處理身體。例如, GET和HEAD絕不能具有身體,但是諸如DELETE和OPTIONS類的方法可能具有身體,並且如果對您的應用有意義,則應進行有條件處理的身體。
.stream
ReadableStream<Uint8Array>它將允許在Uint8Array塊中讀取身體。這是Fetch API Request中的.body屬性。
.used
如果使用身體,則設置為true ,否則將其設置為false 。
它也有幾種方法:
arrayBuffer()
用一個包含身體內容(如果有)的ArrayBuffer來解決。適用於閱讀/處理二進制數據。
blob()
用包含身體內容物的Blob解決。適用於閱讀/處理二進制數據。
form()
用URLSearchParams解析,該parmes已從身體的內容中解碼。這適用於具有內容類型的application/x-www-form-urlencoded身體。
formData()
用FormData實例解析,該實例已從身體的內容中解碼。這適用於具有內容類型的multipart/form-data的身體。
json()
從人體中解析為JSON的數據解決。如果在應用程序中指定了jsonBodyReviver ,則在解析JSON時將使用它。
text()
用代表身體內容物的字符串解決。
type()
試圖提供有關如何編碼身體的指導,該指導可用於確定用於解碼身體的方法。該方法返回一個表示解釋的身體類型的字符串:
| 價值 | 描述 |
|---|---|
"binary" | 該身體具有指示二進制數據的內容類型,並且應使用.arrayBuffer() ,. .blob()或.stream應用於讀取身體。 |
"form" | 主體被編碼為表單數據,應使用.form()讀取身體。 |
"form-data" | 身體被編碼為多部分形式,應使用.formData()讀取身體。 |
"json" | 將身體編碼為JSON數據,並應使用.json()來讀取身體。 |
"text" | 身體被編碼為文本,並且應使用.text()來讀取身體。 |
"unknown" | 要么沒有身體,要么無法根據內容類型確定身體類型。 |
.type()方法還採用可選的自定義媒體類型的參數,這些媒體類型將在嘗試確定身體類型時使用。然後將它們合併到默認媒體類型中。該值是一個對象,其中鍵是binary , form , form-data , json或text的對象之一,並且該值是與類型IS格式兼容的格式的適當媒體類型。
context.response包含有關響應的信息,這些信息將發送回請求者。它包含幾個屬性:
.body
響應的主體通常可以通過下面記錄的自動響應主體來處理。
.headers
Headers實例,其中包含響應的標題。
.status
HTTP Status代碼將帶迴響應。如果在響應之前未設置此設置,則橡木將默認為200 OK如果有一個.body ,則404 Not Found 。
.type
介質類型或擴展名為響應設置Content-Type標頭。例如,您可以提供txt或text/plain原來描述身體。
和幾種方法:
.redirect(url?: string | URL | REDIRECT_BACK, alt?: string | URL)
一種簡化將響應重定向到另一個URL的方法。它將將Location標頭設置為所提供的url ,並將狀態302 Found (除非狀態已經是3XX狀態)。使用符號REDIRECT_BACK作為url表示請求中的Referer標頭應作為方向,如果未設置Referer ,則alt為替代位置。如果既沒有設置alt和Referer ,則重定向將發生到/ 。基本的HTML(如果請求者支持它)或將設置文本主體,以解釋它們正在重定向。
.toDomResponse()
這將轉換橡木的信息了解對提取API Response的響應。這將最終確定響應,從而進一步嘗試修改投擲的響應。這旨在在橡木中內部使用,以便能夠響應請求。
.with(response: Response)
這設置了對Web標準Response的響應。請注意,這將忽略/覆蓋其他中間件設置的任何其他信息,包括要設置的標題或cookie之類的內容。
當響應Content-Type未設置在.response的標題中時,Oak將自動嘗試確定適當的Content-Type 。首先,它將查看.response.type 。如果分配,它將嘗試基於將.type作為媒體類型的值或基於擴展解決媒體類型解決適當的媒體類型。例如,如果.type設置為"html" ,則Content-Type將設置為"text/html" 。
如果未設置.type的值,則OAK將檢查.response.body的值。如果值是string ,則橡木將檢查字符串看起來是否像HTML,如果是的,則將設置為Content-Type text/html否則將其設置為text/plain 。如果值是一個對象,除了Uint8Array , Deno.Reader或null之外,該對象將傳遞給JSON.stringify() ,並且Content-Type將設置為application/json 。
如果身體類型是數字,bigint或符號,則將其脅迫到字符串並將其視為文本。
如果身體的值是一個函數,則該函數將在沒有參數的情況下調用。如果該函數的返回值是有希望的,那將是等待的,並且解決值將如上所述處理。如果值不承諾,則將如上所述處理。
應用方法.listen()用於打開服務器,開始偵聽請求以及為每個請求處理註冊的中間件。當服務器關閉時,此方法將返回承諾。
服務器打開後,在開始處理請求之前,應用程序將啟動"listen"事件,可以通過.addEventListener()方法來偵聽。例如:
import { Application } from "jsr:@oak/oak/application" ;
const app = new Application ( ) ;
app . addEventListener ( "listen" , ( { hostname , port , secure } ) => {
console . log (
`Listening on: ${ secure ? "https://" : "http://" } ${
hostname ?? "localhost"
} : ${ port } ` ,
) ;
} ) ;
// register some middleware
await app . listen ( { port : 80 } ) ;如果要關閉應用程序,則該應用程序支持流產信號的選項。這是使用信號的示例:
import { Application } from "jsr:@oak/oak/application" ;
const app = new Application ( ) ;
const controller = new AbortController ( ) ;
const { signal } = controller ;
// Add some middleware using `app.use()`
const listenPromise = app . listen ( { port : 8000 , signal } ) ;
// In order to close the server...
controller . abort ( ) ;
// Listen will stop listening for requests and the promise will resolve...
await listenPromise ;
// and you can do something after the close to shutdown中間件可用於處理中間件的其他錯誤。等待其他中間件在捕獲錯誤時執行。因此,如果您有一個錯誤處理中間件,可以對錯誤進行良好的響應,則可以這樣奏效:
import { Application } from "jsr:@oak/oak/application" ;
import { isHttpError } from "jsr:@oak/commons/http_errors" ;
import { Status } from "jsr:@oak/commons/status" ;
const app = new Application ( ) ;
app . use ( async ( ctx , next ) => {
try {
await next ( ) ;
} catch ( err ) {
if ( isHttpError ( err ) ) {
switch ( err . status ) {
case Status . NotFound :
// handle NotFound
break ;
default :
// handle other statuses
}
} else {
// rethrow if you can't handle the error
throw err ;
}
}
} ) ;該應用程序將捕獲未接收的中間件例外。 Application擴展了DENO中的全局EventTarget ,當中間軟件或發送響應中未知錯誤時, EventError將被派發到該應用程序。要收聽這些錯誤,您將在應用程序實例中添加一個事件處理程序:
import { Application } from "jsr:@oak/oak/application" ;
const app = new Application ( ) ;
app . addEventListener ( "error" , ( evt ) => {
// Will log the thrown error to the console.
console . log ( evt . error ) ;
} ) ;
app . use ( ( ctx ) => {
// Will throw a 500 on every request.
ctx . throw ( 500 ) ;
} ) ;
await app . listen ( { port : 80 } ) ; Router類生產中間件,可與Application一起使用,以根據請求的路徑名啟用路由。
下面的示例提供了一份書籍地圖的恢復服務,其中http://localhost:8000/book/將返回一系列書籍, http://localhost:8000/book/1將帶有ID返回書籍"1" :
import { Application } from "jsr:@oak/oak/application" ;
import { Router } from "jsr:@oak/oak/router" ;
const books = new Map < string , any > ( ) ;
books . set ( "1" , {
id : "1" ,
title : "The Hound of the Baskervilles" ,
author : "Conan Doyle, Arthur" ,
} ) ;
const router = new Router ( ) ;
router
. get ( "/" , ( context ) => {
context . response . body = "Hello world!" ;
} )
. get ( "/book" , ( context ) => {
context . response . body = Array . from ( books . values ( ) ) ;
} )
. get ( "/book/:id" , ( context ) => {
if ( books . has ( context ?. params ?. id ) ) {
context . response . body = books . get ( context . params . id ) ;
}
} ) ;
const app = new Application ( ) ;
app . use ( router . routes ( ) ) ;
app . use ( router . allowedMethods ( ) ) ;
await app . listen ( { port : 8000 } ) ;通過使用regexp的路徑將通道轉換為正則表達式,這意味著在模式中表達的參數將被轉換。 path-to-regexp具有高級用法,可以創建可用於匹配的複雜模式。如果您有高級用例,請查看該庫的文檔。
在大多數情況下, context.params的類型。params是從路徑模板字符串通過打字稿魔術自動推斷出來的。但是,在更複雜的情況下,這可能不會產生正確的結果。在這種情況下,您可以使用router.get<RouteParams>覆蓋該類型,其中RouteParams是context.params的顯式類型。
支持嵌套路由器。以下示例響應http://localhost:8000/forums/oak/posts and http://localhost:8000/forums/oak/posts/nested-routers 。
import { Application } from "jsr:@oak/oak/application" ;
import { Router } from "jsr:@oak/oak/router" ;
const posts = new Router ( )
. get ( "/" , ( ctx ) => {
ctx . response . body = `Forum: ${ ctx . params . forumId } ` ;
} )
. get ( "/:postId" , ( ctx ) => {
ctx . response . body =
`Forum: ${ ctx . params . forumId } , Post: ${ ctx . params . postId } ` ;
} ) ;
const forums = new Router ( ) . use (
"/forums/:forumId/posts" ,
posts . routes ( ) ,
posts . allowedMethods ( ) ,
) ;
await new Application ( ) . use ( forums . routes ( ) ) . listen ( { port : 8000 } ) ; 該函數send()旨在作為中間件功能的一部分提供靜態內容。在最直截了當的用法中,提供了一個根,並通過本地文件系統從請求的路徑相對於root提供了向函數提供的請求。
基本用法看起來像這樣:
import { Application } from "jsr:@oak/oak/application" ;
const app = new Application ( ) ;
app . use ( async ( context , next ) => {
try {
await context . send ( {
root : ` ${ Deno . cwd ( ) } /examples/static` ,
index : "index.html" ,
} ) ;
} catch {
await next ( ) ;
}
} ) ;
await app . listen ( { port : 8000 } ) ; send()自動支持諸如在響應中提供ETag和Last-Modified標頭,以及請求中的If-None-Match If-Modified-Since標頭等功能。這意味著,在提供靜態內容時,客戶將能夠依靠其資產的緩存版本,而不是重新下載它們。
send()方法自動支持為靜態資產生成ETag標頭。標題允許客戶端確定是否需要重新下載資產,但是計算其他方案的ETag s可能很有用。
有一個中間件功能來評估context.reponse.body ,並確定它是否可以為該體型創建ETag標頭,如果這樣,則將ETag標頭設置為響應。基本用法看起來像這樣:
import { Application } from "jsr:@oak/oak/application" ;
import { factory } from "jsr:@oak/oak/etag" ;
const app = new Application ( ) ;
app . use ( factory ( ) ) ;
// ... other middleware for the application還有一個函數,它基於將其讀取到內存中邏輯的內容來檢索一個實體,該函數可以傳遞給ETAG計算的ETAG,這是DENO STD庫的一部分:
import { Application } from "jsr:@oak/oak/application" ;
import { getEntity } from "jsr:@oak/oak/etag" ;
import { calculate } from "jsr:@std/http/etag" ;
const app = new Application ( ) ;
// The context.response.body has already been set...
app . use ( async ( ctx ) => {
const entity = await getEntity ( ctx ) ;
if ( entity ) {
const etag = await calculate ( entity ) ;
}
} ) ; Deno.serve()遷移如果您是從Deno.serve()或為Web標準提取API Request和Response設計的調整代碼的遷移,則有幾個橡木功能可以提供幫助。
ctx.request.source在DENO下運行時,將設置為Fetch API Request ,直接訪問原始請求。
ctx.response.with()此方法將接受提取API Response ,或根據提供的BodyInit和ResponseInit創建新響應。這也將最終確定響應,忽略橡木.response上可能設置的任何內容。
middleware/serve#serve()和middelware/serve#route()這兩個中間件生成器可用於調整更像Deno.serve()操作的代碼,因為它提供了Fetch API Request ,並期望處理程序通過Fetch API Response解決。
使用serve()與Application.prototype.use() :
import { Application } from "jsr:@oak/oak/application" ;
import { serve } from "jsr:@oak/oak/serve" ;
const app = new Application ( ) ;
app . use ( serve ( ( req , ctx ) => {
console . log ( req . url ) ;
return new Response ( "Hello world!" ) ;
} ) ) ;
app . listen ( ) ;並且類似的解決方案可與route()一起使用,其中上下文包含有關路由器的信息,例如參數:
import { Application } from "jsr:@oak/oak/application" ;
import { Router } from "jsr:@oak/oak/router" ;
import { route } from "jsr:@oak/oak/serve" ;
const app = new Application ;
const router = new Router ( ) ;
router . get ( "/books/:id" , route ( ( req , ctx ) => {
console . log ( ctx . params . id ) ;
return Response . json ( { title : "hello world" , id : ctx . params . id } ) ;
} ) ) ;
app . use ( router . routes ( ) ) ;
app . listen ( ) ; mod.ts導出一個名為testing的對象,其中包含一些用於測試您可能創建的橡木中間件的實用程序。有關更多信息,請參見使用Oak的測試。
有幾個模塊直接從其他模塊進行調整。他們保留了個人許可和版權。所有模塊,包括直接調整的模塊均根據MIT許可獲得許可。
所有其他工作都是版權2018-2024橡樹作者。版權所有。