zoukankan      html  css  js  c++  java
  • koa简介

    资料来源:
    http://javascript.ruanyifeng.com/nodejs/koa.html
    http://koa.bootcss.com/

    以下内容为摘抄,纯属做笔记加深印象。勿喷。

    使用 koa 编写 web 应用,通过组合不同的 generator,可以免除重复繁琐的回调函数嵌套,并极大地提升错误处理的效率。一个Koa应用就是一个对象,包含了一个middleware数组,这个数组由一组Generator函数组成。这些函数负责对HTTP请求进行各种加工,比如生成缓存、指定代理、请求重定向等等。这些中间件函数基于 request 请求以一个类似于栈的结构组成并依次执行。

    Koa 包含了像 content-negotiation(内容协商)、cache freshness(缓存刷新)、proxy support(代理支持)和 redirection(重定向)等常用任务方法。 与提供庞大的函数支持不同,Koa只包含很小的一部分,因为Koa并不绑定任何中间件。

    中间件

    Koa的中间件很像Express的中间件,也是对HTTP请求进行处理的函数,但是必须是一个Generator函数。而且,Koa的中间件是一个级联式(Cascading)的结构,也就是说,属于是层层调用,第一个中间件调用第二个中间件,第二个调用第三个,以此类推。上游的中间件必须等到下游的中间件返回结果,才会继续执行,这点很像递归。

    中间件通过当前应用的use方法注册。

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

    Generator函数内部使用yield命令,将程序的执行权转交给下一个中间件,即yield next,要等到下一个中间件返回结果,才会继续往下执行。只要有一个中间件缺少yield next语句,后面的中间件都不会执行,这一点要引起注意。

    如果想跳过一个中间件,可以直接在该中间件的第一行语句写上return yield next

    app.use(function* (next) {
      if (skip) return yield next;
    })

    由于Koa要求中间件唯一的参数就是next,导致如果要传入其他参数,必须另外写一个返回Generator函数的函数。

    function logger(format) {
      return function *(next){
        var str = format
          .replace(':method', this.method)
          .replace(':url', this.url);
    
        console.log(str);
    
        yield next;
      }
    }
    
    app.use(logger(':method :url'));

    路由

    可以通过this.path属性,判断用户请求的路径,从而起到路由作用。

    app.use(function* (next) {
      if (this.path === '/') {
        this.body = 'we are at home!';
      } else {
        yield next;
      }
    })

    复杂的路由需要安装koa-router插件。

    var app = require('koa')();
    var Router = require('koa-router');
    
    var myRouter = new Router();
    
    myRouter.get('/', function *(next) {   //router.get方法的第一个参数是根路径,第二个参数是对应的函数方法。
      this.response.body = 'Hello World!';
    });
    
    app.use(myRouter.routes());
    
    app.listen(3000);

    Koa-router实例提供一系列动词方法,即一种HTTP动词对应一种方法。典型的动词方法有以下五种。

    • router.get()
    • router.post()
    • router.put()
    • router.del()
    • router.patch()

    这些动词方法可以接受两个参数,第一个是路径模式,第二个是对应的控制器方法(中间件),定义用户请求该路径时服务器行为。

    Koa-router允许为路径统一添加前缀。
    var router = new Router({
      prefix: '/users'
    });
    
    router.get('/', ...); // 等同于"/users"
    router.get('/:id', ...); // 等同于"/users/:id"

    app.listen(...)

    Koa 应用并非是一个 1-to-1 表征关系的 HTTP 服务器。 一个或多个Koa应用可以被挂载到一起组成一个包含单一 HTTP 服务器的大型应用群。

    如下为一个绑定3000端口的简单 Koa 应用,其创建并返回了一个 HTTP 服务器。

    var koa = require('koa');
    var app = koa();
    app.listen(3000);

    app.callback()

    返回一个适合 http.createServer() 方法的回调函数用来处理请求。 您也可以使用这个回调函数将您的app挂载在 Connect/Express 应用上。

    app.use(function)

    为应用添加指定的中间件,https://github.com/koajs/koa/wiki#middleware,也就是向middleware数组添加Generator函数。

    app.keys=

    设置签名Cookie密钥,该密钥会被传递给 KeyGrip。

    自己生成秘钥实例:

    app.keys = ['im a newer secret', 'i like turtle'];
    app.keys = new KeyGrip(['im a newer secret', 'i like turtle'], 'sha256');

    错误处理

    默认情况下Koa会将所有错误信息输出到 stderr,除非 NODE_ENV 是 "test"。为了实现自定义错误处理逻辑(比如 centralized logging),您可以添加 "error" 事件监听器。

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

    Context(上下文)

    Koa Context 将 node 的 request 和 response 对象封装在一个单独的对象里面,其为编写 web 应用和 API 提供了很多有用的方法。

    context 在每个 request 请求中被创建,在中间件中作为接收器(receiver)来引用,或者通过 this 标识符来引用:

    app.use(function *(){
      this; // is the Context
      this.request; // is a koa Request
      this.response; // is a koa Response
    });

    CSRF攻击

    CSRF攻击是指用户的session被劫持,用来冒充用户的攻击。

    koa-csrf插件用来防止CSRF攻击。原理是在session之中写入一个秘密的token,用户每次使用POST方法提交数据的时候,必须含有这个token,否则就会抛出错误。

    数据压缩

    koa-compress模块可以实现数据压缩。

    app.use(require('koa-compress')())
    app.use(function* () {
      this.type = 'text/plain'
      this.body = fs.createReadStream('filename.txt')
    })

    API

    • ctx.req
      Node 的 request 对象。

    • ctx.res
      Node 的 response 对象。

    • ctx.request
      Koa 的 Request 对象。

    • ctx.response
      Koa 的 Response 对象。

    • ctx.app
      应用实例引用。

    • ctx.cookies.get(name, [options])
      获得 cookie 中名为 name 的值,options 为可选参数:

      • 'signed': 如果为 true,表示请求时 cookie 需要进行签名。
    • ctx.cookies.set(name, value, [options])
      设置 cookie 中名为 name 的值,options 为可选参数:

      • signed: 是否要做签名
      • expires: cookie 有效期时间
      • path: cookie 的路径,默认为 /'
      • domain: cookie 的域
      • secure: false 表示 cookie 通过 HTTP 协议发送,true 表示 cookie 通过 HTTPS 发送。
      • httpOnly: true 表示 cookie 只能通过 HTTP 协议发送
    • ctx.throw(msg, [status])
      抛出包含 .status 属性的错误,默认为 500。该方法可以让 Koa 准确的响应处理状态。

     

    请求(Request)API

    Koa Request 对象是对 node 的 request 进一步抽象和封装,提供了日常 HTTP 服务器开发中一些有用的功能。

    • req.header
      请求头对象

    • req.method
      请求方法

    • req.method=
      设置请求方法,在实现中间件时非常有用,比如 methodOverride()。

    • req.length
      以数字的形式返回 request 的内容长度(Content-Length),或者返回 undefined。

    • req.url
      获得请求url地址。

    • req.url=
      设置请求地址,用于重写url地址时。

    • req.originalUrl
      获取请求原始地址。

    • req.path
      获取请求路径名。

    • req.path=
      设置请求路径名,并保留请求参数(就是url中?后面的部分)。

    • req.querystring
      获取查询参数字符串(url中?后面的部分),不包含 ?。

    • req.querystring=
      设置查询参数。

    • req.search
      获取查询参数字符串,包含 ?。

    • req.search=
      设置查询参数字符串。

    • req.host

    • req.hostname

    • req.charset

    • req.query
      将查询参数字符串进行解析并以对象的形式返回,如果没有查询参数字字符串则返回一个空对象。

    • req.query=
      根据给定的对象设置查询参数字符串。

    • req.fresh
      检查请求缓存是否 "fresh"(内容没有发生变化)。该方法用于在 If-None-Match / ETag, If-Modified-Since 和 Last-Modified 中进行缓存协调。当在 response headers 中设置一个或多个上述参数后,该方法应该被使用。

    this.set('ETag', '123');
    
    // cache is ok
    if (this.fresh) {
      this.status = 304;
      return;
    }
    
    // cache is stale
    // fetch new data
    this.body = yield db.find('something');  
    • req.stale
      与 req.fresh 相反。

    • req.protocol
      返回请求协议,"https" 或者 "http"。 当 app.proxy 设置为 true 时,支持 X-Forwarded-Host。

    • req.secure
      简化版 this.protocol == "https",用来检查请求是否通过 TLS 发送。

    • req.ip
      请求远程地址。 当 app.proxy 设置为 true 时,支持 X-Forwarded-Host。

    • req.is(type)
      检查请求所包含的 "Content-Type" 是否为给定的 type 值。 如果没有 request body,返回 undefined。 如果没有 content type,或者匹配失败,返回 false。 否则返回匹配的 content-type。

    // With Content-Type: text/html; charset=utf-8
    this.is('html'); // => 'html'
    this.is('text/html'); // => 'text/html'
    this.is('text/*', 'text/html'); // => 'text/html'
    
    // When Content-Type is application/json
    this.is('json', 'urlencoded'); // => 'json'
    this.is('application/json'); // => 'application/json'
    this.is('html', 'application/*'); // => 'application/json'
    
    this.is('html'); // => false
    • req.accepts(types)
      检查给定的类型 types(s) 是否可被接受,当为 true 时返回最佳匹配,否则返回 false。type 的值可以是一个或者多个 mime 类型字符串。

    • req.acceptsEncodings(encodings)
      检查 encodings 是否可以被接受,当为 true 时返回最佳匹配,否则返回 false。 注意:您应该在 encodings 中包含 identity。

    // Accept-Encoding: gzip
    this.acceptsEncodings('gzip', 'deflate', 'identity');
    // => "gzip"
    
    this.acceptsEncodings(['gzip', 'deflate', 'identity']);
    // => "gzip"
    • req.acceptsCharsets(charsets)
      检查 charsets 是否可以被接受,如果为 true 则返回最佳匹配, 否则返回 false。
    // Accept-Charset: utf-8, iso-8859-1;q=0.2, utf-7;q=0.5
    this.acceptsCharsets('utf-8', 'utf-7');
    // => "utf-8"
    
    this.acceptsCharsets(['utf-7', 'utf-8']);
    // => "utf-8"
    • req.socket
      返回请求的socket。

    • req.get(field)
      返回请求 header 中对应 field 的值。

     

    响应(Response)API

    Koa Response 对象是对 node 的 response 进一步抽象和封装,提供了日常 HTTP 服务器开发中一些有用的功能。

    • res.header
      Response header 对象。

    • res.socket
      Response socket。

    • res.status
      获取 response status。不同于 node 在默认情况下 res.statusCode 为200,res.status 并没有赋值。

    • res.statusString
      Response status 字符串。

    • res.status=
      通过数字状态码或者不区分大小写的字符串来设置response status.

    • res.length=
      通过给定值设置 response Content-Length。

    • res.length
      如果 Content-Length 作为数值存在,或者可以通过 res.body 来进行计算,则返回相应数值,否则返回 undefined。

    • res.body
      获得 response body。

    • res.body=

    • res.get(field)
      获取 response header 中字段值,field 不区分大小写。

    var etag = this.get('ETag');
    • res.set(field, value)
      设置 response header 字段 field 的值为 value。
    this.set('Cache-Control', 'no-cache');
    • res.set(fields)
      使用对象同时设置 response header 中多个字段的值。
    this.set({
      'Etag': '1234',
      'Last-Modified': date
    });
      • res.remove(field)
        移除 response header 中字段 filed。

      • res.type
        获取 response Content-Type,不包含像 "charset" 这样的参数。

      • res.type=
        通过 mime 类型的字符串或者文件扩展名设置 response Content-Type.

      • res.redirect(url, [alt])
        执行 [302] 重定向到对应 url。

      • res.lastModified
        如果存在 Last-Modified,则以 Date 的形式返回。

      • res.lastModified=
        以 UTC 格式设置 Last-Modified。您可以使用 Date 或 date 字符串来进行设置。

      • res.append(field, val)
        在 header 的 field 后面 追加 val。

      • res.vary(field)
        相当于执行res.append('Vary', field)。

  • 相关阅读:
    CodeForces 156B Suspects(枚举)
    CodeForces 156A Message(暴力)
    CodeForces 157B Trace
    CodeForces 157A Game Outcome
    HDU 3578 Greedy Tino(双塔DP)
    POJ 2609 Ferry Loading(双塔DP)
    Java 第十一届 蓝桥杯 省模拟赛 19000互质的个数
    Java 第十一届 蓝桥杯 省模拟赛 19000互质的个数
    Java 第十一届 蓝桥杯 省模拟赛 19000互质的个数
    Java 第十一届 蓝桥杯 省模拟赛十六进制转换成十进制
  • 原文地址:https://www.cnblogs.com/zourong/p/6048157.html
Copyright © 2011-2022 走看看