1.前言

这篇我们一起来学习 Context ,Request,Response,这 3 个最常用的 Api。

2.上下文(Context)

Koa Context 将 node 的 requestresponse 对象封装到单个对象中,为编写 Web 应用程序和 API 提供了许多有用的方法。通过这种上下文的方式,使用起来比较方便, 这些操作在 HTTP 服务器开发中频繁使用,它们被添加到此级别而不是更高级别的框架,这将强制中间件重新实现此通用功能。
每个 请求都将创建一个 Context,并在中间件中作为接收器引用,或者 ctx 标识符,如以下代码片段所示:

  1. app.use(async ctx => {
  2. ctx; // 这是 Context
  3. ctx.request; // 这是 koa Request
  4. ctx.response; // 这是 koa Response
  5. });

为方便起见许多上下文的访问器和方法直接委托给它们的 ctx.requestctx.response ,不然的话它们是相同的。 例如 ctx.typectx.length 委托给 response 对象,ctx.pathctx.method 委托给 request

2.1 ctx.req

Node 的 request 对象。

2.2 ctx.res

Node 的 response 对象。
绕过 Koa 的 response 处理是 不被支持的. 应避免使用以下 node 属性:

  • res.statusCode
  • res.writeHead()
  • res.write()
  • res.end()

    在使用过程中,我们应该尽量避免使用ctx.req,ctx.res,这这个对象是绕过了 Koa 来处理 Http请求的 request 和 response,会出现一些意想不到的问题。

    2.3 ctx.request

    koa 的 Request 对象。

    2.4 ctx.response

    koa 的 Response 对象。

    2.5 ctx.app

    应用程序实例引用。

    2.6 ctx.cookies.get(name, [options])

    通过 options 获取 cookie name:

  • signed 所请求的cookie应该被签名

koa 使用 cookies模块,其中只需传递参数。

2.7 ctx.cookies.set(name, value, [options])

通过 options 设置 cookie namevalue :

  • maxAge 一个数字表示从 Date.now() 得到的毫秒数
  • signed cookie 签名值
  • expires cookie 过期的 Date
  • path cookie 路径, 默认是'/'
  • domain cookie 域名
  • secure 安全 cookie
  • httpOnly 服务器可访问 cookie, 默认是 true
  • overwrite 一个布尔值,表示是否覆盖以前设置的同名的 cookie (默认是 false). 如果是 true, 在同一个请求中设置相同名称的所有 Cookie(不管路径或域)是否在设置此Cookie 时从 Set-Cookie 标头中过滤掉。

koa 使用传递简单参数的 cookies 模块。

2.8 ctx.throw([status], [msg], [properties])

Helper 方法抛出一个 .status 属性默认为 500 的错误,这将允许 Koa 做出适当地响应。
允许以下组合:

  1. ctx.throw(400);
  2. ctx.throw(400, 'name required');
  3. ctx.throw(400, 'name required', { user: user });
  4. 例如 ctx.throw(400, 'name required') 等效于:
  5. const err = new Error('name required');
  6. err.status = 400;
  7. err.expose = true;
  8. throw err;

2.9 ctx.respond

为了绕过 Koa 的内置 response 处理,你可以显式设置 ctx.respond = false;。 如果您想要写入原始的 res 对象而不是让 Koa 处理你的 response,请使用此参数。
请注意,Koa 支持使用此功能。这可能会破坏 Koa 中间件和 Koa 本身的预期功能。使用这个属性被认为是一个 hack,只是便于那些希望在 Koa 中使用传统的 fn(req, res) 功能和中间件的人。

3 Request 别名

以下访问器和 Request别名等效:

  • ctx.header
  • ctx.headers
  • ctx.method
  • ctx.method=
  • ctx.url
  • ctx.url=
  • ctx.originalUrl
  • ctx.origin
  • ctx.href
  • ctx.path
  • ctx.path=
  • ctx.query
  • ctx.query=
  • ctx.querystring
  • ctx.querystring=
  • ctx.host
  • ctx.hostname
  • ctx.fresh
  • ctx.stale
  • ctx.socket
  • ctx.protocol
  • ctx.secure
  • ctx.ip
  • ctx.ips
  • ctx.subdomains
  • ctx.is()
  • ctx.accepts()
  • ctx.acceptsEncodings()
  • ctx.acceptsCharsets()
  • ctx.acceptsLanguages()
  • ctx.get()

    4. Response 别名

    以下访问器和 Response别名等效:

  • ctx.body

  • ctx.body=
  • ctx.status
  • ctx.status=
  • ctx.message
  • ctx.message=
  • ctx.length=
  • ctx.length
  • ctx.type=
  • ctx.type
  • ctx.headerSent
  • ctx.redirect()
  • ctx.attachment()
  • ctx.set()
  • ctx.append()
  • ctx.remove()
  • ctx.lastModified=
  • ctx.etag=

    5. 请求(Request)

    Koa Request 对象是在 node 的 vanilla 请求对象之上的抽象,提供了诸多对 HTTP 服务器开发有用的功能。

    5.1 列举几个工作中常用的 api

假设我们现在有个 get请求 http://localhost:3000/user/detail/1?name=3434,下面代码打印了我们常用的几个属性,更多可以看官方api。

  1. function detail(ctx) {
  2. const id = ctx.params.id;
  3. const { request, response } = ctx;
  4. console.log(request.headers)
  5. console.log(request.query) // { name: '3434' }
  6. console.log(request.method) // GET
  7. console.log(request.url) // /user/detail/1?name=3434
  8. console.log(request.originalUrl) // /user/detail/1?name=3434
  9. console.log(request.href) // /user/detail/1?name=3434
  10. console.log(request.path) // /user/detail/1
  11. console.log(request.querystring) // name=3434
  12. console.log(request.type)
  13. ctx.body = {
  14. data: array[id],
  15. success: true
  16. }
  17. }
  18. module.exports = {
  19. detail,
  20. list
  21. }

5.1.1 request.header

请求标头对象,使用 request.headers 也是可以的。

5.1.2 request.query

获取解析的查询字符串, 当没有查询字符串时,返回一个空对象。请注意,此 getter 支持嵌套解析。
例如 “color=blue&size=small”:

  1. {
  2. color: 'blue',
  3. size: 'small'
  4. }

5.1.3 request.method

请求方法。

5.1.4 request.url

获取请求 URL。

5.1.5 request.originalUrl

获取请求原始URL。

5.1.6 request.href

获取完整的请求URL,包括 protocolhosturl

  1. ctx.request.href;
  2. // => http://example.com/foo/bar?q=1

5.1.7 request.path

获取请求路径名。

5.1.8 request.path=

设置请求路径名,并在存在时保留查询字符串。

5.1.9 request.querystring

根据 ? 获取原始查询字符串。

5.1.10 request.querystring=

设置原始查询字符串。

5.1.11 request.search

使用 ? 获取原始查询字符串。

5.2 request.type

获取请求 Content-Type 不含参数 “charset”。

  1. const ct = ctx.request.type;
  2. // => "image/png"

6. 响应(Response)

Koa Response 对象是在 node 的 vanilla 响应对象之上的抽象,提供了诸多对 HTTP 服务器开发有用的功能。

  1. const array = [{id: 0, name: '王二'}, {id: 1, name: '赵三'}]
  2. function detail(ctx) {
  3. ctx.response.body = {
  4. data: array[id],
  5. success: true
  6. }
  7. ctx.response.set("hc-test", 1)
  8. ctx.response.status = 200
  9. }
  10. // 或者通过 上面 ctx Response 别名
  11. function detail(ctx) {
  12. ctx.body = {
  13. data: array[id],
  14. success: true
  15. }
  16. ctx.status = 200
  17. }

上面这段代码是基本使用,可以看到使用起来还是非常方便。

6.1 常用API

6.1.1 response.headers

响应标头对象。别名是 response.header

6.1.2 response.status

获取响应状态。

6.1.3 response.status=

通过数字代码设置响应状态,常见的如 200,404, 301, 302。如果 response.status 未被设置, Koa 将会自动设置状态为 200204

6.1.4 response.body

获取响应主体。

6.1.5 response.body=

将响应体设置为以下之一:

  • string 写入
  • Buffer 写入
  • Stream 管道
  • Object || Array JSON-字符串化
  • null 无内容响应
    6.1.6 String
    Content-Type 默认为 text/htmltext/plain, 同时默认字符集是 utf-8。Content-Length 字段也是如此。
    6.1.7 Object
    Content-Type 默认为 application/json. 这包括普通的对象 { foo: 'bar' } 和数组 ['foo', 'bar']
    6.1.8 Buffer
    Content-Type 默认为 application/octet-stream, 并且 Content-Length 字段也是如此。
    6.1.9 Stream
    Content-Type 默认为 application/octet-stream
    每当流被设置为响应主体时,.onerror 作为侦听器自动添加到 error 事件中以捕获任何错误。此外,每当请求关闭(甚至过早)时,流都将被销毁。如果你不想要这两个功能,请勿直接将流设为主体。例如,当将主体设置为代理中的 HTTP 流时,你可能不想要这样做,因为它会破坏底层连接。
    以下是流错误处理的示例,而不会自动破坏流:
    1. const PassThrough = require('stream').PassThrough;
    2. app.use(async ctx => {
    3. ctx.body = someHTTPStream.on('error', ctx.onerror).pipe(PassThrough());
    4. });

    6.1.10 response.set(field, value)

    设置响应标头 fieldvalue:
    1. ctx.set('Cache-Control', 'no-cache');

    6.1.11 response.set(fields)

    用一个对象设置多个响应标头fields:
    1. ctx.set({
    2. 'Etag': '1234',
    3. 'Last-Modified': date
    4. });

    6.1.12 response.remove(field)

    删除标头 field

    6.1.13 response.redirect(url, [alt])

    执行 [302] 重定向到 url.
    字符串 “back” 是特别提供Referrer支持的,当Referrer不存在时,使用 alt 或“/”。
    1. ctx.redirect('back');
    2. ctx.redirect('back', '/index.html');
    3. ctx.redirect('/login');
    4. ctx.redirect('http://google.com');
    要更改 “302” 的默认状态,只需在该调用之前或之后分配状态。要变更主体请在此调用之后:
    1. ctx.status = 301;
    2. ctx.redirect('/cart');
    3. ctx.body = 'Redirecting to shopping cart';

    7 小结

    这节我们总结了 上下文 Context, Request,Response 的基本使用,这3 个对象在平常使用中最频繁,大家要好好掌握,因为 这个3个对象下挂载了非常多的属性,方法,平常使用过程中,不知道了可以查查官方文档,对应代码 koa-context