koa文檔參考

koa文檔

簡介

koa 是由 Express 原班人馬打造的,致力於成爲一個更小、更富有表現力、更健壯的 Web 框架。使用 koa 編寫 web 應用,經過組合不一樣的 generator,能夠免除重複繁瑣的回調函數嵌套,並極大地提高錯誤處理的效率。koa 不在內核方法中綁定任何中間件,它僅僅提供了一個輕量優雅的函數庫,使得編寫 Web 應用變得駕輕就熟。html

koa1.x的用generator, koa2.x用async/await, node各個版本對es6的支持程度,可參考 node.greennode

Koa 應用是一個包含一系列中間件 generator 函數的對象。 這些中間件函數基於 request 請求以一個相似於棧的結構組成並依次執行。 Koa 相似於其餘中間件系統(好比 Ruby's Rack 、Connect 等), 然而 Koa 的核心設計思路是爲中間件層提供高級語法糖封裝,以加強其互用性和健壯性,並使得編寫中間件變得至關有趣。git

Koa 包含了像 content-negotiation(內容協商)、cache freshness(緩存刷新)、proxy support(代理支持)和 redirection(重定向)等經常使用任務方法。 與提供龐大的函數支持不一樣,Koa只包含很小的一部分,由於Koa並不綁定任何中間件。es6

hello world示例:github

//koa 2.x
var Koa = require('koa');
var app = new Koa();
app.use(async (ctx, next) => {
    ctx.body = 'Hello World';
});
app.listen(3000);
console.log('server listening at 3000');

中間件

Koa 的中間件經過一種更加傳統(您也許會很熟悉)的方式進行級聯,摒棄了以往 node 頻繁的回調函數形成的複雜代碼邏輯。 咱們經過 generators 來實現「真正」的中間件。 Connect 簡單地將控制權交給一系列函數來處理,直到函數返回。 與之不一樣,當執行到 yield next 語句時,Koa 暫停了該中間件,繼續執行下一個符合請求的中間件('downstrem'),而後控制權再逐級返回給上層中間件('upstream')。web

koa1.x 和 koa2.x的中間件機制是同樣的,區別在於koa1.x用generator書寫,koa2.x用async/await; async/await本質上是generator的語法糖,generator的本質是一個迭代器,須要runner去觸發下一階段的執行.
中間件的棧執行順序(後進先出),相似html標籤層層嵌套,從頂層到底層,在從底層開始閉合(其實dom的事件機制也相似)json

示例:緩存

//> koa 2.x
var Koa = require('koa');
var app = new Koa();
// mw: x-response-time
app.use(async (ctx,next) => {
    let start = new Date;
    await next();
    let ms = new Date - start;
    ctx.set('X-Response-time', ms + 'ms');
});

// mw: logger
app.use(async (ctx, next) => {
    let start  = new Date;
    await next();
    let ms = new Date - start;
    console.log('%s %s - %d', ctx.method, ctx.url, ms);
});

// mw: response
app.use(async (ctx, next) => {
    ctx.body = 'Hello World'; // 設置響應內容後,還能夠 ctx.se(..) 設置響應頭
});

app.listen(3012);
console.log('server listening at 3012');


//> koa 1.x
var koa = require('koa');
var app = koa();

// x-response-time
app.use(function* (next) {
    let start = new Date;
    yield next;
    var ms = new Date - start;
    this.set('X-Response-Time', ms + 'ms');
});

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

// response
app.use(function* (next) {
    this.body = 'Hello World~~';
});

app.listen(3012);
console.log('server listen at 3012');

配置

app實例的配置屬性:服務器

  • app.name 應用名稱
  • app.env 環境變量(默認爲 process.env.NODE_ENV || 'development')
  • app.proxy 若爲true, 則解析header(請求頭),並支持 X-Forwarded-Host
  • app.subdomainOffset 默認2,表示 app.subdomains, 所忽略的segment個數

app.listen(port)

app.listen(3000) 建立並返回一個http服務器.cookie

// app.listen() 同下
var http = require('http');
http.createServer(app.callback()).listen(3000);
http.createServer(app.callback()).listen(3001); // 同一個應用運行在多個端口上

app.callback()

app.callback() 返回request callback函數,可用於 http.createServer(app.callback())

app.use(middleware)

app.use(mw) 爲應用添加中間件

app.keys

app.keys = ['i am secrect', 'hello'] 設置 signed cookie 的密鑰

ctx.cookies.set('name', 'sandy', {signed: true}) 設置加密的cookie

錯誤處理

默認全部的錯誤信息會輸出到 stderr, 能夠監聽error事件,實現自動的錯誤處理.

app.on('error', function(err, context) {
    // 若處理請求階段出錯,不能響應時,會有context參數傳入回調
    console.error('server error:', err);
});

上下文對象

Koa Context 將 node 的 request 和 response 對象封裝在一個單獨的對象裏面,其爲編寫 web 應用和 API 提供了不少有用的方法。

context 在每一個 request 請求中被建立.

koa 1.x 的上下文對象爲中間件的 this, koa 2.x 的上下文對象,爲中間件的參數1

// koa 1.x
app.use(function* (next) {
    this.body = 'good'; // this is context obj
});

// koa 2.x
app.use(async (ctx, next) => {
    ctx.body = 'good2'; // ctx is context obj
});

爲了便於訪問和調用,許多 context 的屬性和方法,代理了 ctx.request 和 ctx.response 所對應的等價方法, 好比說 ctx.type 和 ctx.length 代理了 response 對象中對應的方法,ctx.path 和 ctx.method 代理了 request 對象中對應的方法。

  • ctx.req nodejs的request對象
  • ctx.res nodejs的response對象
  • ctx.request koa的request對象, 包裝後的nodejs的request對象
  • ctx.response koa的response對象
  • ctx.app 應用實例的引用
  • ctx.cookies.get(name, [options]) 獲取coolie, koa使用了Express的cookies模塊
  • ctx.cookies.set(name, value, [options]) 設置cookie,

    options = {
          signed: true, 
          expires: time, 
          path: '/', 
          domain: 'a.com', 
          secure: false, 
          httpOnly: true
      }
  • ctx.throw(msg, [status]) 拋出異常

    // 適配 msg status兩個參數的順序,缺乏的則用默認值
      ctx.throw(403);
      ctx.throw('some error'); 
      ctx.throw('name required', 400);
      ctx.throw(400, 'name required');
  • ctx.response ctx.response = false 時,能夠經過ctx.res直接使用原生的response對象, 但不推薦這樣作

  • ctx.request對象釋放到 ctx上的方法和屬性

    // url and method
    • ctx.url
    • ctx.originalUrl read only
    • ctx.protocol read only
    • ctx.host read only
    • ctx.hostname read only
    • ctx.path
    • ctx.query
    • ctx.querystring
    • ctx.method
    // header
    • ctx.header read only
    • ctx.get(headerName)
    • ctx.is() 判斷 content-type
    • ctx.accepts() accepts content-type
    • ctx.acceptsEncodings()
    • ctx.acceptsLanguage()
    • ctx.accepetsCharsets()
    // others
    • ctx.ip read only
    • ctx.ips read only
    • ctx.secure read only
    • ctx.subdomains read only
    • ctx.fresh read only
    • ctx.stale read only
    • ctx.socket read only
  • ctx.response對象釋放到 ctx 上的方法和屬性

    // 響應體
    • ctx.body
    • ctx.attachment()
    // 響應頭
    • ctx.set(name,val) 設置響應頭
    • ctx.remove() 刪除響應頭
    • ctx.status 狀態碼
    • ctx.length content-length
    • ctx.type content-type
    • ctx.lastModified 緩存相關響應頭
    • ctx.etag
    // 其餘
    • ctx.headerSent 是否已發送響應頭
    • ctx.redirect() 重定向
  • ctx.request對象的完整屬性方法

    // url and method
    • ctx.request.method
    • ctx.request.url
    • ctx.request.originalUrl
    • ctx.request.protocol
    • ctx.request.host hostname:port
    • ctx.request.hostname
    • ctx.request.path
    • ctx.request.query eg: {color: 'blue', size: 'small'} 不支持嵌套對象
    • ctx.request.querystring eg: foo=bar&go=fine
    • ctx.request.search eg: ?foo=bar&go=fine
    // header
    • ctx.request.get()
    • ctx.request.header
    • ctx.request.type content-type eg: image/png
    • ctx.request.length cotent-length
    • ctx.request.charset eg: utf-8
    • ctx.request.is() eg: ctx.is('html'), ctx.is('text/html'), ctx.is('html', 'application/*'), ctx.is('application/json')
    // others
    • ctx.request.fresh 若用(*If-None-Match/ETag, If-Modified-Since/Last-Modified)進行緩存協商,則該屬性表示協商結果
    • ctx.request.stale 與 ctx.request.fresh 相反
    • ctx.request.secure
    • ctx.request.ip
    • ctx.request.ips
    • ctx.request.subdomains
    • ctx.request.socket
    • ctx.request.idempotent 請求是否冪等
    // 內容協商
    • ctx.request.accepts(types) eg: ctx.accepts('html') ctx.accepets('json', 'text')
    • ctx.request.acceptsEncoding(encodings) eg: ctx.acceptsEncodings('gzip', 'deflate','identity')
    • ctx.request.acceptsLanguages(langs) eg: this.acceptsLanguages('es', 'en')
    • ctx.request.acceptsCharsets(charsets) eg: ctx.acceptsCharsets('utf-8')
  • ctx.response對象的完整屬性

    // 響應體
    • ctx.response.body eg: ctx.body = String/Buffer/Stream/Object
    • ctx.response.attachment([filename])
    // 響應頭
    • ctx.response.get(field) eg: ctx.response.get('ETag') 響應頭(field)不區分大小寫
    • ctx.response.set(field, value) eg: ctx.set('cache-control', 'no-cache')
    • ctx.response.remove(field)
    • ctx.response.append(field, val) 爲指定頭部追加值
    • ctx.response.header
    • ctx.response.status eg: ctx.response.status = 301;
    • ctx.response.statusString
    • ctx.response.length content-length
    • ctx.response.type content-type eg: image/png , .png , png
    • ctx.response.lastModified eg: ctx.lastModified = new Date()
    • ctx.response.etag eg: ctx.response.etag = crypto.createHash('md5').update(ctx.body).digest('hex');
    // 其餘
    • ctx.response.headerSent
    • ctx.response.vary(field) 等價於 ctx.response.append('Vary', field)
    • ctx.response.socket
    • ctx.response.redirect(url, [alt])

      ctx.redirect('back');
        ctx.redirect('back', '/index.html')
        ctx.redirect('/login');
        ctx.redirect('http://google.com');
相關文章
相關標籤/搜索