Промежуточное программное обеспечение для нативного HTTP -сервера Deno, Deno Deploy, Node.js 16.5, а затем, работники Cloudflare и Bun. Это также включает в себя промежуточный маршрутизатор.
Этот промежуточный фреймворк вдохновлен KOA и промежуточным программным обеспечением, вдохновленным @KOA/Router.
Этот Readme фокусируется на механике APIS Oak API и предназначена для тех, кто знаком с фреймворками промежуточного программного обеспечения JavaScript, такими как Express и KOA, а также достойное понимание DEDO. Если вы не знакомы с ними, пожалуйста, ознакомьтесь с документацией на Oakserver.github.io/OAK.
Кроме того, ознакомьтесь с нашими часто задаваемыми вопросами и удивительным сайтом ресурсов сообщества.
Примечание
Примеры в этом притяжении ReadMe от main и предназначены для DeNo CLI или Deno Deploy, что может не иметь смысла делать, когда вы хотите фактически развернуть рабочую нагрузку. Вы хотели бы «прикрепить» к конкретной версии, которая совместима с версией Deno, которую вы используете, и имеет фиксированный набор API, которые вы ожидаете. https://deno.land/x/ поддерживает использование тегов GIT в URL, чтобы направить вас в определенной версии. Таким образом, чтобы использовать версию 13.0.0 Oak, вы хотели бы импортировать 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" ;Дуб доступен для node.js как на NPM, так и на JSR. Чтобы использовать из 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/HTTPS в настоящее время не поддерживаются.
Кроме того, среда CloudFlare Worker и контекст выполнения в настоящее время не подвержены промежуточному программному обеспечению.
Дуб доступен для работников CloudFlare на JSR. Чтобы использовать добавление пакета в свой проект CloudFlare Worker:
npx jsr add @oak/oak@14
А затем импортируйте в модуль:
import { Application } from "@oak/oak/application" ;В отличие от других времен выполнения, приложение Oak не прислушивается к входящим запросам, вместо этого оно обрабатывает запросы работников. Минимальный пример сервера будет:
import { Application } from "@oak/oak/application" ;
const app = new Application ( ) ;
app . use ( ( ctx ) => {
ctx . response . body = "Hello CFW!" ;
} ) ;
export default { fetch : app . fetch } ; Примечание
Обновления Send и WebSocket в настоящее время не поддерживаются.
Дуб доступен для Bun на JSR. Чтобы использовать Установка пакета:
bunx jsr i @oak/oak@14
А затем импортируйте в модуль:
import { Application } from "@oak/oak/application" ; Примечание
Обновления Send и 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 или информации о том, как установить CLI DENO, ознакомьтесь с руководством 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 } ) ; Чтобы true HTTPS -сервер, опции app.listen() должны .certFile параметр .secure Параметры .keyFile .
.handle() Метод Метод .handle() используется для обработки запросов и получения ответов без приложения управлять аспектом сервера. Это, хотя и является расширенным использованием, и большинство пользователей захотят использовать .listen() .
Метод .handle() принимает до трех аргументов. Первым является аргумент Request , а второй - аргумент Deno.Conn . Третий необязательный аргумент - это флаг, указывающий, был ли запрос «безопасным» в том смысле, что он возник из соединения TLS с удаленным клиентом. Метод разрешился с помощью объекта Response или undefined если ctx.respond === true .
Пример:
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 - необязательная функция ревиверса, которая будет применена при чтении тел 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
Это будет undefined если соединение не было обновлено до веб -сокета. Если соединение было обновлено, будет установлен интерфейс .socket .
.state
Запись о состоянии приложения, которая может быть сильно напечатана путем указания общего аргумента при построении Application() или выводится путем передачи объекта состояния (например Application({ state }) ).
Контекст, переданный в промежуточное программное обеспечение, имеет некоторые методы:
.assert()
Сделает утверждение, которое, если не верно, бросает HTTPError , который подкласс идентифицируется вторым аргументом, а сообщение является третьим аргументом.
.send()
Поток файла запрашивающему клиенту. См. Статический контент ниже для получения дополнительной информации.
.sendEvents()
Преобразовать текущее соединение в ответ на событие сервера и вернуть сервера ServerSentEventTarget , где сообщения и события могут быть переданы клиенту. Это false .respond
.throw()
Бросает HTTPError , который подкласс идентифицируется первым аргументом, причем сообщение передается как второе.
.upgrade()
Попытайтесь обновить подключение к подключению к веб -сокетам и вернуть интерфейс WebSocket . Предыдущая версия Oak, это было бы Promise разрешить с помощью веб -сокета std/ws .
В отличие от других промежуточных рамках, context не имеет значительного количества псевдонимов. Информация о запросе находится только в .request , и информация о ответе находится только в .response
context.cookies позволяет получить доступ к значениям файлов cookie в запросе и позволяет создавать файлы cookie в ответ. Он автоматически закрепляет файлы cookie, если свойство .keys установлено в приложении. Поскольку .cookies использует API -интерфейсы веб -криптографии для подписи и проверки файлов cookie, и эти API работают асинхронным образом, API -файлы cookie работают асинхронно. Он имеет несколько методов:
.get(key: string, options?: CookieGetOptions): Promise<string | undefined>
Попытки извлечь файл cookie из запроса и вернуть значение cookie на основе ключа. Если приложения .keys установлены, то 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
Умеренное это будет удалено в будущем выпуске дуба.
Запрос «необработанного» NativeServer , который является абстракцией над объектом Request DOM. .originalRequest.request - это экземпляр Request DOM, который обрабатывается. Пользователи, как правило, должны избегать их использования.
.secure
Ярлык для .protocol , возвращая true если HTTPS в противном случае false .
.source
При запуске под DeDo. .source будет установлен на Request Source Web Standard. При запуске под Nodejs это будет undefined .
.url
Экземпляр URL , который основан на полном URL -адресах для запроса. Это находится вместо того, чтобы открыть части URL -адреса на остальной части объекта запроса.
И несколько методов:
.accepts(...types: string[])
Переговоряет о типе контента, поддерживаемом запросом на ответ. Если типы контента не передаются, метод возвращает приоритетный массив принятых типов контента. Если типы контента передаются, лучший тип контента возвращается. Если не возвращается undefined , не возвращается.
.acceptsEncodings(...encodings: string[])
Переговоры о кодировании контента, поддерживаемом запросом на ответ. Если кодировки не передаются, метод возвращает приоритетный массив принятых кодировки. Если кодировки передаются, лучшая договорная кодировка возвращается. Если никаких кодировки не соответствуют undefined возвращается.
.acceptsLanguages(...languages: string[])
Договорится о языке, который клиент может понять. Где вариант локали принимает предпочтения. Если кодировки не передаются, метод возвращает приоритетный массив изученных языков. Если языки пройдены, лучший договорной язык возвращается. Если языки не соответствуют undefined возвращается.
Важный
Этот API значительно изменился в Oak V13 и позже. Предыдущий API вырос органически с тех пор, как Oak был создан в 2018 году и не представлял какого -либо другого общего API. API, введенный в V13, лучше выравнивается с Request API Fetch API, и должен быть более знаком для разработчиков, впервые приезжающих в Оук.
API для запроса дуба .body Тело вдохновляется Request API Fetch, но с некоторыми функциональными возможностями. 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 . Это похоже на .body Request
.used
Установите true , если тело было использовано, в противном случае установите на false .
У этого также есть несколько методов:
arrayBuffer()
Решает с помощью ArrayBuffer , который содержит содержимое тела, если таковые имеются. Подходит для чтения/обработки двоичных данных.
blob()
Решает с помощью Blob , которая содержит содержимое тела. Подходит для чтения/обработки двоичных данных.
form()
Решает с помощью URLSearchParams , которые были декодированы из содержимого тела. Это подходит для тела с типом содержимого 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 , а значение является подходящим типом носителя в формате, совместимых с форматом типа.
context.response содержит информацию о ответе, которая будет отправлена обратно в запросчик. Он содержит несколько свойств:
.body
Корпус ответа, который часто можно обрабатывать с помощью автоматической обработки тела ответа, документированной ниже.
.headers
Экземпляр Headers , который содержит заголовки для ответа.
.status
Код Status HTTP, который будет отправлен обратно с ответом. Если это не будет 404 Not Found , прежде чем ответить, Oak по умолчанию по умолчанию в 200 OK , если есть .body
.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 в запросе должен использоваться в качестве направления, причем alt является альтернативным местоположением, если Referer не установлен. Если ни alt , ни Referer не установлены, перенаправление произойдет до / . Будет установлен базовый HTML (если запрашиватель поддерживает его) или текстовое тело, объясняющее, что они перенаправляются.
.toDomResponse()
Это преобразует информационный дуб, понимающий ответ на Response API Fetch. Это завершит ответ, что приведет к дальнейшей попытке изменить ответ на бросок. Это предназначено для использования внутри дуба, чтобы иметь возможность отвечать на запросы.
.with(response: Response) и .with(body?: BodyInit, init?: ResponseInit)
Это устанавливает ответ на веб Response . Обратите внимание, что это игнорирует/переопределяет любую другую информацию, установленную на ответе другого промежуточного программного обеспечения, включая такие вещи, как заголовки или файлы cookie.
Content-Type Content-Type ответа не установлен в .response . Сначала он будет смотреть на .response.type . Если назначено, он попытается разрешить соответствующий тип носителя на основе рассматриваемого значения .type как типа носителя, либо разрешения типа носителя на основе расширения. Например, если .type был установлен на "html" , то Content-Type будет установлен на "text/html" .
Если .type не установлен со значением, то Oak осмотрит значение .response.body . Если значение является string , то Oak проверит, если строка выглядит как HTML, если да, Content-Type будет установлен в text/html иначе она будет установлена на text/plain . Если значение является объектом, кроме Uint8Array , Deno.Reader или null , объект будет передаваться в JSON.stringify() , а Content-Type будет установлен в application/json .
Если тип тела - это число, биглинт или символ, он будет принужден к строке и рассматривается как текст.
Если значение тела является функцией, функция будет вызвана без аргументов. Если возвращаемое значение функции обещают, это будет ожидается, и разрешенное значение будет обработано, как указано выше. Если значение не обещает, оно будет обработано, как указано выше.
Метод приложения .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 расширяет глобальную EventTarget в DEDO, и когда в промежуточном программном обеспечении возникают ошибки, или отправка ответов, 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 } ) ; Переданный маршрут преобразуется в регулярное выражение с использованием пути к режиме, что означает, что параметры, выраженные в шаблоне, будут преобразованы. path-to-regexp имеет расширенное использование, которое может создавать сложные шаблоны, которые можно использовать для сопоставления. Проверьте документацию для этой библиотеки, если у вас есть расширенные варианты использования.
В большинстве случаев тип context.params Params автоматически выводится из строки шаблона пути через магию TypeScript. Однако в более сложных сценариях это может не дать правильный результат. В этом случае вы можете переопределить тип с помощью router.get<RouteParams> , где RouteParams является явным типом для context.params .
Гнездовые маршрутизаторы поддерживаются. Следующий пример отвечает на http://localhost:8000/forums/oak/posts и 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() предназначена для обслуживания статического контента как часть функции промежуточного программного обеспечения. В наиболее простом использовании корень предоставляется, и запросы, предоставленные функции, выполняются с файлами из локальной файловой системы относительно корня из запрошенного пути.
Основное использование будет выглядеть примерно так:
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 для других сценариев.
ETag функция ETag программного обеспечения, которая оценивает context.reponse.body . Основное использование будет выглядеть примерно так:
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, который является частью библиотеки 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() или адаптируя код, который предназначен для Request и Response Web Standard Fetch API, существует несколько функций дуба, чтобы помочь.
ctx.request.source При запуске под Deno это будет установлено на Request API Fetch, предоставляя прямой доступ к исходному запросу.
ctx.response.with() Этот метод примет Response API Fetch или создаст новый ответ на основе предоставленного BodyInit и ResponseInit . Это также завершит ответ и игнорирует все, что могло быть установлено на дубе .response
middleware/serve#serve() и middelware/serve#route() Эти два генератора промежуточного программного обеспечения могут использоваться для адаптации кода, который работает больше похож на Deno.serve() в том смысле, что он обеспечивает Request API Fetch и ожидает, что обработчик разрешит с помощью Response API Fetch.
Пример использования 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 , который содержит некоторые утилиты для тестирования промежуточного программного обеспечения, которое вы можете создать. Смотрите тестирование с дубом для получения дополнительной информации.
Есть несколько модулей, которые непосредственно адаптированы из других модулей. Они сохранили свои индивидуальные лицензии и авторские права. Все модули, в том числе те, которые непосредственно адаптируются, лицензированы по лицензии MIT.
Вся дополнительная работа - Copyright 2018 - 2024, The Oak Authors. Все права защищены.