Giter VIP home page Giter VIP logo

koa's Introduction

Koa middleware framework for nodejs

gitter NPM version build status Test coverage OpenCollective Backers OpenCollective Sponsors PR's Welcome

Expressive HTTP middleware framework for node.js to make web applications and APIs more enjoyable to write. Koa's middleware stack flows in a stack-like manner, allowing you to perform actions downstream then filter and manipulate the response upstream.

Only methods that are common to nearly all HTTP servers are integrated directly into Koa's small ~570 SLOC codebase. This includes things like content negotiation, normalization of node inconsistencies, redirection, and a few others.

Koa is not bundled with any middleware.

Installation

Koa requires node v12 or higher for ES2015 and async function support.

$ npm install koa

Hello Koa

const Koa = require('koa');
const app = new Koa();

// response
app.use(ctx => {
  ctx.body = 'Hello Koa';
});

app.listen(3000);

Getting started

  • Kick-Off-Koa - An intro to Koa via a set of self-guided workshops.
  • Workshop - A workshop to learn the basics of Koa, Express' spiritual successor.
  • Introduction Screencast - An introduction to installing and getting started with Koa

Middleware

Koa is a middleware framework that can take two different kinds of functions as middleware:

  • async function
  • common function

Here is an example of logger middleware with each of the different functions:

async functions (node v7.6+)

app.use(async (ctx, next) => {
  const start = Date.now();
  await next();
  const ms = Date.now() - start;
  console.log(`${ctx.method} ${ctx.url} - ${ms}ms`);
});

Common function

// Middleware normally takes two parameters (ctx, next), ctx is the context for one request,
// next is a function that is invoked to execute the downstream middleware. It returns a Promise with a then function for running code after completion.

app.use((ctx, next) => {
  const start = Date.now();
  return next().then(() => {
    const ms = Date.now() - start;
    console.log(`${ctx.method} ${ctx.url} - ${ms}ms`);
  });
});

Koa v1.x Middleware Signature

The middleware signature changed between v1.x and v2.x. The older signature is deprecated.

Old signature middleware support will be removed in v3

Please see the Migration Guide for more information on upgrading from v1.x and using v1.x middleware with v2.x.

Context, Request and Response

Each middleware receives a Koa Context object that encapsulates an incoming http message and the corresponding response to that message. ctx is often used as the parameter name for the context object.

app.use(async (ctx, next) => { await next(); });

Koa provides a Request object as the request property of the Context.
Koa's Request object provides helpful methods for working with http requests which delegate to an IncomingMessage from the node http module.

Here is an example of checking that a requesting client supports xml.

app.use(async (ctx, next) => {
  ctx.assert(ctx.request.accepts('xml'), 406);
  // equivalent to:
  // if (!ctx.request.accepts('xml')) ctx.throw(406);
  await next();
});

Koa provides a Response object as the response property of the Context.
Koa's Response object provides helpful methods for working with http responses which delegate to a ServerResponse .

Koa's pattern of delegating to Node's request and response objects rather than extending them provides a cleaner interface and reduces conflicts between different middleware and with Node itself as well as providing better support for stream handling. The IncomingMessage can still be directly accessed as the req property on the Context and ServerResponse can be directly accessed as the res property on the Context.

Here is an example using Koa's Response object to stream a file as the response body.

app.use(async (ctx, next) => {
  await next();
  ctx.response.type = 'xml';
  ctx.response.body = fs.createReadStream('really_large.xml');
});

The Context object also provides shortcuts for methods on its request and response. In the prior examples, ctx.type can be used instead of ctx.response.type and ctx.accepts can be used instead of ctx.request.accepts.

For more information on Request, Response and Context, see the Request API Reference, Response API Reference and Context API Reference.

Koa Application

The object created when executing new Koa() is known as the Koa application object.

The application object is Koa's interface with node's http server and handles the registration of middleware, dispatching to the middleware from http, default error handling, as well as configuration of the context, request and response objects.

Learn more about the application object in the Application API Reference.

Documentation

Troubleshooting

Check the Troubleshooting Guide or Debugging Koa in the general Koa guide.

Running tests

$ npm test

Reporting vulnerabilities

To report a security vulnerability, please do not open an issue, as this notifies attackers of the vulnerability. Instead, please email dead_horse, jonathanong, and niftylettuce to disclose.

Authors

See AUTHORS.

Community

Job Board

Looking for a career upgrade?

Backers

Support us with a monthly donation and help us continue our activities.

Sponsors

Become a sponsor and get your logo on our README on Github with a link to your site.

License

MIT

koa's People

Contributors

tj avatar jonathanong avatar dead-horse avatar dependabot[bot] avatar tejasmanohar avatar fengmk2 avatar fl0w avatar PlasmaPower avatar juliangruber avatar tinovyatkin avatar stojanovic avatar targos avatar initial-wu avatar Pana avatar doug-wade avatar ianstormtaylor avatar jamesgeorge007 avatar nickmccurdy avatar joehecn avatar 3imed-jaberi avatar Foxandxss avatar neighborhood999 avatar iyuq avatar fundon avatar yoshuawuyts avatar panva avatar ilkkao avatar Jeff-Tian avatar mingmingwon avatar mgol avatar

Stargazers

春风化雨 avatar  avatar  avatar Jorge Barrera avatar Ryota Sakai avatar Avimitin Lu avatar zhou avatar Anshuman Chhapolia avatar  avatar  avatar Amogh Lele avatar Li-xing Yang avatar  avatar Sergiu Strat avatar Pedro Machado Santa avatar  avatar  avatar  avatar MartianiYuqiong avatar Roger Ye avatar Christian Gaggero avatar actually akac avatar  avatar Mofeng avatar Farid Vatani avatar EGuozhi avatar Yugang Cao avatar 一个大兵 avatar  avatar Binh Nguyen avatar  avatar  avatar Aryan Iyappan avatar yanggggjie avatar Rubek Joshi avatar Ao Zhang - 张 傲 avatar whale avatar 박효진 avatar Gabriel Trigo avatar Total Cue avatar  avatar /^[at]florent$/ avatar Anonimus Programus avatar elvis avatar  avatar Antônio Ribeiro avatar Matteo Azzolini avatar Sam avatar Gabriel Dias Mazieri avatar LiFuHai avatar Ashish avatar Aaron Zemetres avatar Miqueas avatar Pedro Mascarenhas avatar xiaogao avatar 南北、 avatar Archger avatar zanlaodai avatar Grason Chan avatar İsmail Karslı avatar Issac Leyva avatar 双霖 avatar  avatar  avatar Jakub Albert Ferenc avatar  avatar QuentinHsu avatar Haonan Su avatar  avatar Pavel Kalbovich avatar NorthEgg avatar Waldir Bertazzi Junior avatar  avatar Prasanta Singh avatar Lov`u`e avatar Mike avatar  avatar Adrian Yang avatar Paolo Dapul avatar  avatar  avatar viyk avatar 杨腾宇 avatar Hajidalakhtar avatar ChamRun avatar Eric Chan avatar  avatar Chinge_Yang avatar 述不作 avatar Seanx avatar  avatar Michael avatar  avatar 道友请留步 avatar  avatar  avatar Aydoğan avatar Olivier Mourlevat avatar  avatar 江智彬 avatar

Watchers

Robert Sköld avatar Mike Ball avatar Alexey Simonenko avatar arden avatar ippa avatar Stig Kleppe-Jørgensen avatar Rex Chung avatar blackthought286 avatar zbage avatar Fangdun Tsai avatar Travis Cooper avatar  avatar Abhik Khanra avatar  avatar Ford Guo avatar Jeff Fox avatar Teej.PinoyTech avatar Douglas Wilson avatar Ji Can avatar Martin Iwanowski avatar Masaaki Kurihara avatar Abhijeet Kaulgud avatar Jawf avatar Greco Shi avatar Craig Sharkie avatar Nguyen Tien Si avatar sharper avatar Vu avatar Avindra Goolcharan avatar Thiago Magalhães avatar André Philip avatar Hilton Gonçalves avatar Brad Walker avatar Jinsang.Park avatar ToucheComm avatar fengmk2 avatar davidwei_001 avatar jack zheng avatar junlei zhang avatar Reggie Zhang avatar evandrix avatar Allen Galler avatar qbaty avatar Homa avatar Mustafa Kahraman avatar Chuck Yang avatar Peter Schmidler avatar yury avatar Cristiano Contin avatar Yuan Chuan avatar enmaai avatar send2vinnie avatar  avatar Chua Kiem Fai avatar Toni avatar wxnet2013 avatar Rodrigo Oliveira avatar Terry Xu avatar Nick Chan avatar Mehdi Lefebvre avatar keepallsimple avatar David Posin avatar Richard Hess avatar yoneal avatar Ricardo Torres avatar 穿山甲 avatar  avatar Haoliang Gao avatar Jason Paul Cole avatar Christian Hochfilzer avatar dingyun avatar  avatar Zsolt Takács avatar vitrum.zhu avatar  avatar  avatar Ronalds avatar 叶晓毅 avatar Angel Marino avatar Damien Chaillou avatar xuhaixiang avatar yiqing avatar Masakazu Matsushita avatar d avatar guoguofish avatar mayulu avatar ryan avatar BruceChen avatar Mitch Okamoto avatar Jamacy avatar  avatar  avatar Ricardo Campos avatar Tony Liu avatar  avatar ney chang avatar Jonathan Matthey avatar Lea Hayes avatar Miguel avatar Evgenii Kubyshin avatar

koa's Issues

don't touch original req/res

would be nice if koa didn't touch the original req/res. since we're building a wrapper around them, i don't see why it would be necessary.

example is:

  /**
   * Set request URL.
   *
   * @api public
   */

  set url(val) {
    this.req.url = val;
  },

Wish it were something else like:

  get url() {
    return this._url || this.req.url
  },

  set url(val) {
    this._url = val
  }

consider domain support (optional?)

seems like we can't really wrap just one stream so we may want to consider this, knocks a good 1000rps off but eh. seems a little tricky to do with middleware since we have to terminate it lower, similar issue to the compress middleware

basic auth

does basic auth really need to be in core?

LICENSE?

update the year to 2013. Also, you should add the repository field to package.json.

consider delegating to ctx.request / ctx.response

In general I don't like this for the average use-case and "hot" methods, but I do prefer this.request.etag to this.get('ETag'), this.request.length, this.response.length, this.response.header etc, but the common cases we have would delegate: this.body = foo == this.response.body = foo. something to think about

yield down

instead of yield next? so used to next() in connect that it mind-fucks me a bit

Why not app.use(generator) ?

Like this

app.use(function *(next) {
    var start = new Date;
    yield next;
    var ms = new Date - start;
    console.log('%s %s - %s', this.method, this.url, ms);
});

Is there a reason for that?

warn if app.context() overwrites another property during development

since we kind of expect developers to attach their own properties to context, it may be nice to warn when a property is overwritten. this is to avoid conflicts with different plugins/extensions/etc. we can also do something like app.context(obj, dontWarnMe) where dontWarnMe is a Boolean and default true during development.

moar middleware

more common shit, all as wrappers for vanilla node libs when appropriate.

  • common logger
  • compression
  • cookie session
  • db session
  • conditional get
  • jsonp
  • etag
  • directory
  • csrf protection
  • request limits
  • rate limiting
  • favicon
  • methodOverride
  • basicAuth
  • route
  • domains
  • static
  • timeout

FAQ

with some design decisions etc

more convenience properties

  • this.response.lastModified = Date() - since i'm too lazy to do this.set('Last-Modified', new Date().toUTCString()). plus we can normalize people's date strings.
  • this.response.etag = '12345' - wrap the etag in "s if not already.
  • this.response.link()
  • this.response.location()

most of the other stuff i can think of are already handled by higher level stuff. or people won't use. if you don't have any opinions on these, i will implement them after you implement this.response and this.request.

remove qs dependency

i personally don't like qs. would be nice if you removed it as a dep and used the native querystring module in core, then moved qs to a separate repo.

app error handling improvements

right now, app.onerror is added to the the error event listener automatically. what happens if users don't want to use it? doing app.removeListener('event', app.onerror)` is a little annoying. instead i suggest the following:

  • remove app.onerror
  • remove app.outputErrors
  • at the app.callback() stage, warn/throw if no event listeners have been added
  • automatically add the default listener in development
app.callback = function(){
  // ...

  if (!app.listeners('error')) {
    if (this.env === 'development') {
      console.warn('You should add your own error handler.');
      app.on('error', function(err) {
        console.error(err.stack);
      })
    } else if (this.env !== 'test') {
      throw new Error('Add your own error handler!');
    }
  }

  return function(req, res){
  // ..
})

app.mixin()

since we will have app.context(), app.request(), and app.response(), i guess we should have something like app.mixin() where you can do:

app.mixin({
  context: {},
  request: {},
  response: {}
})

so you can do with a plugin:

app.mixin(require('koa-context-something'))

maybe app.plugin(). maybe a different, better name. also, an app.inherit(parentapp) would be nice as well, especially if you mount apps.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.