Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

A small, but powerful HTTP library for Deno & Deno Deploy, built for convenience and simplicity

License

NotificationsYou must be signed in to change notification settings

zaiste/wren

Repository files navigation

wren: a small, but powerful HTTP library for Deno & Deno Deploy

Wren is a small, but powerful HTTP library for Deno & Deno Deploy, built for convenience and simplicity.

import{serve}from"wren/mod.ts";import{GET,POST}from"wren/route.ts";import*asResponsefrom'wren/response.ts';constroutes=[GET('/',()=>Response.OK('Hello, Wren')),POST('/form-post',({ params})=>Response.Created(`Received:${JSON.stringify(params)}`)),];serve(routes);

Getting Started

deno run -A -r https://wren.deno.dev my-wren-project
cd my-wren-project
deno task start

Features

Aliases for HTTP Responses

Wren adds aliases for HTTP responses so that you can not only write them faster (less characters to write), but you use the actual HTTP status names and not the codes.

// with Wrenimport*asResponsefrom'wren/response.ts';// don't forget to configure the import map for this to work// ...somewhere in your handler (type: `Handler`)returnResponse.OK('Your Body');returnResponse.InternalServerError('Your Body');returnResponse.MethodNotAllowed();// without Wrenimport{Status}from"http/http_status.ts";// Deno's HTTP modulereturnnewResponse('Your body',{status:200});returnnewResponse('Your body',{status:Status.OK});returnnewResponse('Something bad ',{status:500});returnnewResponse('Something bad ',{status:Status.InternalServerError});returnnewResponse('',{status:405});returnnewResponse('',{status:Status.MethodNotAllowed});// etc...

Serialization of Plain Objects into JSON Responses

In addition to having less to write when using Wren's aliases for HTTP responses, you can also pass a plain JavaScript object directly to these alias functions, and it will be automatically serialized to a JSON response with the properContent-Type headers (using Deno'sResponse.json() underneath)

returnResponse.OK({source:'XYZ',message:'Something went wrong',code:1234})returnResponse.Created({message:'Widget created successfully',code:777})

Typed JSON Responses

When you return plain JavaScript objects as the body of your responses, it would be great to have a way to define the shape of this data in order to avoid silly mistakes with typos or just to have a tighter interface between your API and its consumers. In Wren, responses can beoptionally typed:

interfaceReturnPayload{source:string;message:string;code:number}returnResponse.OK<ReturnPayload>({source:'XYZ',message:'Something went wrong',code:1234,});// this is OKreturnResponse.OK<ReturnPayload>({surce:'XYZ',// squiggly lines for `surce` + autocomplete in your editormessage:'Something went wrong',code:1234,});

Router

Wren comes with a simple router built around theURLPattern API. It provides two methods: (1)add to register a handler for a specific HTTP method and pathname, and (2)find to retrieve a handler for given HTTP method andRequest's URL.

Wren builds on top of thisRouter to provide theRouting object in a form of aMiddleware (more about middlewares in Wren below).

WithRouting you can define your routing as an array of (potentially nested)Routes.

import{serve}from"http/server.ts";// Deno's HTTP serverimport{GET,POST}from"wren/route.ts";import{Routing}from"wren/routing.ts";import*asResponsefrom'wren/response.ts';constroutes=[GET('/',()=>Response.OK('Hello, Wren')),GET('/hello',()=>Response.Accepted('Hello, again Wren')),POST('/form-post',({ params})=>Response.Created(`Received:${JSON.stringify(params)}`)),]constrouting=Routing(routes);serve(routing);

Instead of using theserve function from Deno's standard library, you can swap it with theserve provided by Wren to pass theroutes array directly.

import{serve}from"wren/mod.ts";import{GET,POST}from"wren/route.ts";import*asResponsefrom'wren/response.ts';constroutes=[  ...];serve(routes);

Parsing ofRequest's Body

Wren automatically parses the URL and the body (based on itsContent-Type) of the incoming request to combine the search params, body params and path params into the additionalparams field of the request.

Quick Reminder:

  • search params come from the URL and are defined after the? sign with each separated by the& sign; e.g.http://example.com?foo=1&bar=baz will be transformed into{ foo: 1, bar: 'baz' } in Wren,
  • body params are the fields sent in the request body and can come from the form submissions, JSON requests or as fields inmultipart,
  • path params are segments of thepathname designated as dynamic e.g./something/:name will be transformed into{ name: 'wren' } in Wren when invoked as/something/wren,

For convenience, Wren combines all those params into a single, readily available object.

In addition to that, when you sentmultipart requests, Wren also provides the uploaded files as the additionalfiles field of the request.

consthandler:Handler=(request)=>{const{ params, files}=request;for(constfileoffiles){// iterate over files to process them or to save them on disk}returnResponse.OK(params)}

The shape for bothparams andfiles is provided as theRequestExtension type not to obscure the built-in Deno'sRequest as defined in the Fetch API.

Composable Middlewares

In Wren middlewares are functions that take a handler as input and return a handler as output - as simple as that! :)

Thus, theMiddleware type is defined as:

typeMiddleware=(handler:Handler)=>Handler

(TBD soon. Check the source code or examples in the meantime)

TypeScript Types

Middleware

TBD

Pipeline

Pipeline represents composition of a series of middlewares over a handler; thus:

typePipeline=[...Middleware[],Handler];

A pipeline is folded or composed in a single handler by applying each middleware onto another and finally on the last handler.

In Wren, middlewares can be defined globally (similar to the.use method in Express), but also locally, i.e. per particular route, which makes it much more flexible in practice than alternatives.

TDB

RequestExtension

RequestExtension definesparams andfiles that are automatically extracted from the incoming request. This type is defined as an intersection type to the built-in Request type so it's less intrusive.

typeHandler=(request:Request&RequestExtension,context:Context)=>Response|Promise<Response>;

Context

About

A small, but powerful HTTP library for Deno & Deno Deploy, built for convenience and simplicity

Topics

Resources

License

Stars

Watchers

Forks


[8]ページ先頭

©2009-2025 Movatter.jp