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-generator或transform-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
當真正的代理頭欄位將被信任時- 忽略
.subdomains
的app.subdomainOffset
偏移量,預設為 2 app.proxyIpHeader
代理 ip 訊息頭, 預設為X-Forwarded-For
app.maxIpsCount
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.context
為ctx
新增其他屬性
錯誤處理
預設情況下,將所有錯誤輸出到 stderr。 當err.status
是404
或err.expose
是true
時不會輸出錯誤。 要執行自定義錯誤處理邏輯,如集中式日誌記錄,可以新增一個 “error” 事件偵聽器
app.on('error', (err, ctx) => { log.error('server error', err, ctx) });
上下文(Context)
Koa Context 將 node 的request
和response
物件封裝到單個物件中,為編寫 Web 應用程式和 API 提供了許多有用的方法
每個請求都將建立一個Context
,並在中介軟體中作為接收器引用,或者ctx
識別符號
API
Context
具體方法和訪問器.
ctx.req Node 的request
物件.
ctx.res Node 的response
物件.
ctx.requestkoa 的Request
物件.
ctx.responsekoa 的Response
物件.
ctx.state推薦的名稱空間,用於通過中介軟體傳遞資訊和前端檢視。
ctx.app 應用程式例項引用
ctx.app.emitKoa 應用擴充套件了內部EventEmitter。ctx.app.emit
發出一個型別由第一個引數定義的事件
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的來源,包括protocol
和host
。
request.hrefNW
獲取完整的請求URL,包括protocol
,host
和url
。
request.path
獲取請求路徑名,並在存在時保留查詢字串。
request.querystring
根據?
獲取原始查詢字串.
request.search
使用?
獲取原始查詢字串。
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-Since
和Last-Modified
之間的快取協商。 在設定一個或多個這些響應頭後應該引用它
request.stale NW
與request.fresh
相反.
request.protocol NW
返回請求協議,“https” 或 “http”。當app.proxy
是true時支援X-Forwarded-Proto
。
request.secure NW
通過ctx.protocol == "https"
來檢查請求是否通過 TLS 發出。
request.ip NW
請求遠端地址。 當app.proxy
是true時支援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
物件包括由accepts和negotiator提供的內容協商實用函式。
這些實用函式是:
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.message
與response.status
關聯.
response.length
以數字返回響應的 Content-Length,或者從ctx.body
推匯出來,或者undefined
。
response.body
獲取響應主體。響應體設定為以下之一:
string
寫入Content-Type 預設為text/html
或text/plain
, 同時預設字符集是 utf-8Buffer
寫入Content-Type 預設為application/octet-stream
Stream
管道Content-Type 預設為application/octet-stream每當流被設定為響應主體時,
.onerror
作為偵聽器自動新增到error
事件中以捕獲任何錯誤。此外,每當請求關閉(甚至過早)時,流都將被銷燬Object
||Array
JSON-字串化Content-Type 預設為application/json
.null
無內容響應
如果response.status
未被設定, Koa 將會自動設定狀態為200
或204
。
response.get(field)
不區分大小寫獲取響應頭欄位值field
response.has(field)
如果當前在響應頭中設定了由名稱標識的訊息頭,不區分大小寫
response.set(field, value)
設定響應頭field
到value
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.etag
getter
response.vary(field)
設定field
的vary
。
response.flushHeaders()
重新整理任何設定的訊息頭,然後是主體(body)。