1. 程式人生 > 實用技巧 >Koa學習筆記(一)簡介

Koa學習筆記(一)簡介

簡介

Koa 是一個新的 web 框架,Express 原班人馬打造, 致力於成為 web 應用和 API 開發領域中的一個更小、更富有表現力、更健壯的基石。 利用 async 函式,丟棄回撥函式,增強錯誤處理。 沒有捆綁任何中介軟體。

Koa 依賴node v7.6.0或 ES2015及更高版本和 async 方法支援. 安裝命令npm i koa

使用 Babel 實現 Async 方法

在 node < 7.6 版本推薦使用babel's require hook.

require('babel-register');
// 應用的其餘 require 需要被放到 hook 後面
const app = require('./app');

.babelrc檔案中, 應該有:transform-async-to-generatortransform-async-to-module-method外掛.

{
  "plugins": ["transform-async-to-generator"]
}

也可以用env preset的 target 引數"node": "current"替代.

應用程式

Koa 應用程式是一個包含一組中介軟體函式的物件,它是按照類似堆疊的方式組織和執行的。

一個關鍵的設計點是在其低階中介軟體層中提供高階“語法糖”,這包括諸如內容協商,快取清理,代理支援和重定向等常見任務的方法

Koa 中介軟體以更傳統的方式級聯,當一箇中間件呼叫next()則該函式暫停並將控制傳遞給定義的下一個中介軟體。當在下游沒有更多的中介軟體執行後,堆疊將展開並且每個中介軟體恢復執行其上游行為

設定

應用程式設定是app例項上的屬性,目前支援如下:

  • app.env預設是NODE_ENV或 "development"
  • app.keys簽名的 cookie 金鑰陣列
  • app.proxy當真正的代理頭欄位將被信任時
  • 忽略.subdomainsapp.subdomainOffset偏移量,預設為 2
  • app.proxyIpHeader代理 ip 訊息頭, 預設為X-Forwarded-For
  • app.maxIpsCount
    從代理 ip 訊息頭讀取的最大 ips, 預設為 0 (代表無限)

app.listen(...)

Koa 應用程式不是 HTTP 伺服器的1對1展現。 可以將一個或多個 Koa 應用程式安裝在一起以形成具有單個HTTP伺服器的更大應用程式

以下是一個無作用的 Koa 應用程式被繫結到3000埠:

const Koa = require('koa');
const app = new Koa();
app.listen(3000);

這裡的app.listen(...)方法只是以下方法的語法糖:

const http = require('http');
const Koa = require('koa');
const app = new Koa();
http.createServer(app.callback()).listen(3000);

這意味著您可以將同一個應用程式同時作為 HTTP 和 HTTPS 或多個地址:

const http = require('http');
const https = require('https');
const Koa = require('koa');
const app = new Koa();
http.createServer(app.callback()).listen(3000);
https.createServer(app.callback()).listen(3001);

app.callback()

返回適用於http.createServer()方法的回撥函式來處理請求。你也可以使用此回撥函式將 koa 應用程式掛載到 Connect/Express 應用程式中。

app.use(function)

將給定的中介軟體方法新增到此應用程式。app.use()返回this, 因此可以鏈式表達.

app.keys=

設定簽名的 Cookie 金鑰。這些被傳遞給KeyGrip,但是你也可以傳遞你自己的KeyGrip例項。

app.context

app.context是從其建立ctx的原型。您可以通過編輯app.contextctx新增其他屬性

錯誤處理

預設情況下,將所有錯誤輸出到 stderr。 當err.status404err.exposetrue時不會輸出錯誤。 要執行自定義錯誤處理邏輯,如集中式日誌記錄,可以新增一個 “error” 事件偵聽器

app.on('error', (err, ctx) => {
  log.error('server error', err, ctx)
});

上下文(Context)

Koa Context 將 node 的requestresponse物件封裝到單個物件中,為編寫 Web 應用程式和 API 提供了許多有用的方法

每個請求都將建立一個Context,並在中介軟體中作為接收器引用,或者ctx識別符號

API

Context具體方法和訪問器.

ctx.req Node 的request物件.

ctx.res Node 的response物件.

繞過 Koa 的 response 處理是不被支援的,如res.write() res.end()等

ctx.requestkoa 的Request物件.

ctx.responsekoa 的Response物件.

ctx.state推薦的名稱空間,用於通過中介軟體傳遞資訊和前端檢視。

ctx.app 應用程式例項引用

ctx.app.emitKoa 應用擴充套件了內部EventEmitterctx.app.emit發出一個型別由第一個引數定義的事件

ctx.cookies.get(name, [options])通過options獲取 cookiename:

ctx.cookies.set(name, value, [options])通過options設定 cookienamevalue:

ctx.throw([status], [msg], [properties])用來丟擲一個包含.status屬性錯誤的幫助方法,其預設值為500。這樣 Koa 就可以做出適當地響應

ctx.throw(400);
ctx.throw(400, 'name required');
ctx.throw(400, 'name required', { user: user });
等同
const err = new Error('name required');
err.status = 400;
err.expose = true;
throw err;

可以根據需要將properties物件傳遞到錯誤中,對於裝載上傳給請求者的機器友好的錯誤是有用的。koa 使用http-errors來建立錯誤。status只應作為第一個引數傳遞

ctx.assert(value, [status], [msg], [properties])!value時丟擲一個類似.throw錯誤的幫助方法。這與 node 的assert()方法類似.koa 使用http-assert作為斷言。

ctx.respond為了繞過 Koa 的內建 response 處理,你可以顯式設定ctx.respond = false;。 如果想要寫入原始的res物件而不是讓 Koa 處理你的 response,請使用此引數,不建議用!!

請求(Request)

KoaRequest物件是在 node 的 原生請求物件之上的抽象,提供了諸多對 HTTP 伺服器開發有用的功能。

API (可讀寫)

request.header

請求頭物件。這與 nodehttp.IncomingMessage上的headers欄位相同

request.headers

請求頭物件。別名為request.header.

request.method

請求方法。

request.length NW

返回以數字返回請求的 Content-Length,或undefined

request.url

獲取請求 URL.對 url 重寫有用。

request.originalUrlNW

獲取請求原始URL。

request.originNW

獲取URL的來源,包括protocolhost

request.hrefNW

獲取完整的請求URL,包括protocolhosturl

request.path

獲取請求路徑名,並在存在時保留查詢字串。

request.querystring

根據?獲取原始查詢字串.

使用?獲取原始查詢字串。

request.hostNW

存在時獲取主機(hostname:port)

request.URLNW

獲取 WHATWG 解析的 URL 物件。

request.typeNW

獲取請求Content-Type, 不含 "charset" 等引數

request.charsetNW

存在時獲取請求字符集,或者undefined

request.query

獲取解析的查詢字串, 當沒有查詢字串時,返回一個空物件 不支援物件巢狀

request.fresh NW

檢查請求快取是否“新鮮”,也就是內容沒有改變。此方法用於If-None-Match/ETag, 和If-Modified-SinceLast-Modified之間的快取協商。 在設定一個或多個這些響應頭後應該引用它

request.stale NW

request.fresh相反.

request.protocol NW

返回請求協議,“https” 或 “http”。當app.proxytrue時支援X-Forwarded-Proto

request.secure NW

通過ctx.protocol == "https"來檢查請求是否通過 TLS 發出。

request.ip NW

請求遠端地址。 當app.proxytrue時支援X-Forwarded-Proto

request.ips

X-Forwarded-For存在並且app.proxy被啟用時,這些 ips 的陣列被返回,從上游 - >下游排序。 禁用時返回一個空陣列

Koa 提供了兩種方式來避免被繞過。

如果您可以控制反向代理,則可以通過調整配置來避免繞過,或者使用 koa 提供的app.proxyIpHeader來避免讀取x-forwarded-for獲取 ips

如果您確切知道伺服器前面有多少個反向代理,則可以通過配置app.maxIpsCount來避免讀取使用者的偽造的請求頭

request.subdomains

以陣列形式返回子域。

例如,如果域名為“tobi.ferrets.example.com”:

如果app.subdomainOffset未設定,ctx.subdomains["ferrets", "tobi"]. 如果app.subdomainOffset是 3,ctx.subdomains["tobi"].

request.is(types...)

檢查傳入請求是否包含Content-Type訊息頭欄位, 並且包含任意的 mimetype

內容協商

Koa 的request物件包括由acceptsnegotiator提供的內容協商實用函式。

這些實用函式是:

  • request.accepts(types)如果提供多種型別,將返回最佳匹配。 如果沒有找到匹配項,則返回一個false,你應該向客戶端傳送一個406 "Not Acceptable"響應。
  • request.acceptsEncodings(types)檢查encodings是否可以接受
  • request.acceptsCharsets(charsets)檢查charsets是否可以接受
  • request.acceptsLanguages(langs)檢查langs是否可以接受

如果沒有提供型別,則返回所有可接受的型別

響應(Response)

KoaResponse物件是在 node 的原生響應物件之上的抽象,提供了諸多對 HTTP 伺服器開發有用的功能。

API

response.header

響應頭物件。

response.headers

響應頭物件。別名是response.header

response.socket

響應套接字。 作為request.socket指向 net.Socket 例項。

response.status

獲取響應狀態。預設情況下,response.status設定為404而不是像 node 的res.statusCode那樣預設為200

response.message

獲取響應的狀態訊息. 預設情況下,response.messageresponse.status關聯.

response.length

以數字返回響應的 Content-Length,或者從ctx.body推匯出來,或者undefined

response.body

獲取響應主體。響應體設定為以下之一:

  • string寫入Content-Type 預設為text/htmltext/plain, 同時預設字符集是 utf-8
  • Buffer寫入Content-Type 預設為application/octet-stream
  • Stream管道Content-Type 預設為application/octet-stream每當流被設定為響應主體時,.onerror作為偵聽器自動新增到error事件中以捕獲任何錯誤。此外,每當請求關閉(甚至過早)時,流都將被銷燬
  • Object||ArrayJSON-字串化Content-Type 預設為application/json.
  • null無內容響應

如果response.status未被設定, Koa 將會自動設定狀態為200204

response.get(field)

不區分大小寫獲取響應頭欄位值field

response.has(field)

如果當前在響應頭中設定了由名稱標識的訊息頭,不區分大小寫

response.set(field, value)

設定響應頭fieldvalue

response.set(fields)

用一個物件設定多個響應頭fields:

response.append(field, value)

用值val附加額外的訊息頭field

response.remove(field)

刪除訊息頭field

response.type

獲取響應Content-Type, 不含 "charset" 等引數,也可設定型別

response.is(types...)

非常類似ctx.request.is(). 檢查響應型別是否是所提供的型別之一

response.redirect(url, [alt])

執行 [302] 重定向到url.要更改 “302” 的預設狀態,只需在該呼叫之前或之後給status賦值

ctx.redirect('back');
ctx.redirect('back', '/index.html');
ctx.redirect('/login');
ctx.redirect('http://google.com');

response.attachment([filename], [options])

Content-Disposition設定為 “附件” 以指示客戶端提示下載

response.headerSent

檢查是否已經發送了一個響應頭。 用於檢視客戶端是否可能會收到錯誤通知。

response.lastModified

Last-Modified訊息頭返回為Date, 如果存在。

response.etag=

設定包含"包裹的 ETag 響應, 請注意,沒有相應的response.etaggetter

response.vary(field)

設定fieldvary

response.flushHeaders()

重新整理任何設定的訊息頭,然後是主體(body)。