nodejs koa入门指引

环境

  • os: macOS Cataline 10.15.4
  • node:v10.20.0 (node v7.6.0 or higher for ES2015 and async function support)
  • npm:6.14.4
  • koa:2.11.0

1. 介绍

Koa是由Express团队设计的一种新的Web框架,由 Express 幕后的原班人马打造, 致力于成为 web 应用和 API 开发领域中的一个更小、更富有表现力、更健壮的基石。通过利用异步功能,Koa允许您不再使用回调并大大提高错误处理能力,避免回调地狱问题。 Koa 并没有捆绑任何中间件, 而是提供了一套优雅的方法,帮助您快速而愉快地编写服务端应用程序。

2. 快速开始

2.1 初始化项目、安装
mkdir koa_test
cd koa_test
npm i koa
2.2 创建app.js
const Koa = require('koa');
const app = new Koa();

app.use(async ctx => {
  ctx.body = 'Hello World';
});

app.listen(3000);
2.3 启动应用
node app.js

浏览器打开http://localhost:3000/,即可看到Hello World

3. 路由

先安装koa-router

npm i koa-router
const Koa = require('koa')
const Router = require('koa-router')

const app = new Koa()
const router =new Router()

router.get('/hello', (ctx) => {
  ctx.body='Hello World'
});
app.use(router.routes()).use(router.allowedMethods());
app.listen(3000);

4. 获取请求参数

4.1 path
const Koa = require('koa')
const Router = require('koa-router')

const app = new Koa()
const router =new Router()

router.get('/hello/:name', (ctx) => {
  ctx.body='Hello World'+','+ctx.params.name
});
app.use(router.routes()).use(router.allowedMethods());
app.listen(3000);

浏览器输入http://localhost:3000/hello/zhangshan
将输出:Hello World,zhangshan

4.2 query

对上一步稍作修改

router.get('/hello', (ctx) => {
  ctx.body='Hello World'+','+ctx.query.name
});

浏览器输入http://localhost:3000/hello?name=zhangshan
将输出:Hello World,zhangshan

对上一步稍作修改

router.get('/hello', (ctx) => {
  ctx.body='Hello World'+','+ctx.querystring
});

浏览器输入http://localhost:3000/hello?name=zhangshan&age=18
将输出:Hello World,name=zhangshan&age=18

4.3 body

需要安装一个中间件koa-body

npm i koa-body

提交body里面的数据要用post请求

const Koa = require('koa')
const Router = require('koa-router')
const bodyParser = require('koa-body')

const app = new Koa()
const router =new Router()

app.use(bodyParser())

router.post('/hello', (ctx) => {
  console.log('body',ctx.request.body)
  ctx.body='Hello World'+','+ctx.request.body.name
});

app.use(router.routes()).use(router.allowedMethods());
app.listen(3000);

我们用postman或用curl模拟请求,

curl -d '{"name":"zhangshan"}' -H "Content-Type: application/json" -X POST http://127.0.0.1:3000/hello

将输出:Hello World,zhangshan

5. 响应数据

5.1 正常
router.post('/hello', (ctx) => {
  console.log('body',ctx.request.body)
  let res='['+ctx.request.body.name+']'
  //status默认值200 可不填
  ctx.response.status=200
  //ctx.response.body等价于ctx.body
  ctx.response.body='Hello World'+','+res;
});

发送一个请求

curl -d '{"name":"zhangshan"}' -H "Content-Type: application/json" -X POST http://127.0.0.1:3000/hello

将输出:Hello World,[zhangshan]

5.2 异常

一种是调用ctx.throw方法,另一种直接抛出err

router.post('/hello', (ctx) => {
  console.log('body',ctx.request.body)
  if(!ctx.request.body.name){
	//ctx.throw(400,'name required'); 等价于下面的 throw err
    const err = new Error('name required');
    err.status = 400;
    //设置为false ,不会显示详细错误信息,这里客户端只显示Bad request
    err.expose = true;
    throw err
  }
  let res='['+ctx.request.body.name+']'
  ctx.response.status=200
  ctx.response.body='Hello World'+','+res;
});

我们不传name属性(name修改成name1了),发送一个请求

curl -d '{"name1":"zhangshan"}' -H "Content-Type: application/json" -X POST http://127.0.0.1:3000/hello

将输出:name required,响应状态码为400

也可以直接修改response

router.post('/hello', (ctx) => {
  console.log('body',ctx.request.body)
  if(!ctx.request.body.name){
          ctx.response.status=400
          ctx.response.message='Bad Reqeust miss args'
          ctx.response.body='name required'
          return
  }
  let res='['+ctx.request.body.name+']'
  //status默认值200 可不填
  ctx.response.status=200
  //ctx.response.body等价于ctx.body
  ctx.response.body='Hello World'+','+res;
});

将输出:name required,响应状态码为400,响应状态消息Bad Reqeust miss args

6. 全局错误处理

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

7. 常用中间件

7.1 koa-logger

用于打印请求数据

const KoaLogger = require('koa-logger');
// access log info
app.use(KoaLogger((str, args) => {
  //Param str is output string with ANSI Color, and you can get pure text with other modules like strip-ansi
  //Param args is a array by [format, method, url, status, time, length]
  logger.debug(str)
}))

eg:

 <-- GET /swagger
 --> GET /swagger 200 1ms 3.86kb
7.2 koa-http-request

用于发送http请求

const koaRequest = require('koa-http-request');
app.use(koaRequest({
    json: true, //automatically parsing of JSON response
    timeout: 3000,    //3s timeout
    host: 'www.baidu.com'
}));
let result = await ctx.get('/'+, {});
console.log(result)
7.3 koa2-swagger-ui

swagger-ui展示,一般还需要其他工具(如swagger-jsdoc)生成openapi json文件

const koaSwagger = require('koa2-swagger-ui');
app.use(
  koaSwagger({
    routePrefix: '/swagger', // host at /swagger instead of default /docs
    swaggerOptions: {
      url: `/api-docs.json`, // example path to json
      hideTopbar: true, // hide swagger top bar
    },
  }),
);
7.4 koa-convert、koa2-cors

跨域设置

const convert = require('koa-convert')
const cors = require('koa2-cors')
app.use(convert(cors({
	allowMethods: ['GET', 'POST','PUT','DELETE'],
    allowHeaders: ['Content-Type', 'Accept'],
    origin: function(ctx) {
        return '*' // 本地环境
    }
})))

7.5 koa-compress

gzip压缩

const compress = require('koa-compress')
app.use(compress({
  threshold: 2048,
  flush: require("zlib").Z_SYNC_FLUSH
}))

参考手册

Application
app.listen(...) //监听某个端口
app.use(function) //使用中间件
app.callback()//返回适合http.createServer() 方法以处理请求的回调函数
app.keys =   //设置签名的Cookie密钥。
app.context  //上下文,可以在上面添加新的属性,以便其他地方引用(增加依赖,反模式)
Context
  // app 引用
  ctx.app
  // 事件
  ctx.app.emit
  //用于通过中间件、前端视图传递信息
  ctx.state
  // is a Koa Request
  ctx.request; 
  // is a Koa Response
  ctx.response; 
  //Node's request object.
  ctx.req;
  //Node's response object. 
  ctx.res 
  //set cookie
  ctx.cookies.set(name, value, [options])  
  //get cookie
  ctx.cookies.get(name, [options]) 
  //抛出异常,返回错误状态码
  ctx.throw([status], [msg], [properties]) 
  // 断言 ,抛出类似于throw()
  ctx.assert(value, [status], [msg], [properties])
  //要绕过Koa的内置响应处理,可以显式设置ctx.respond = false;。如果要写入原始res对象而不是让Koa为您处理响应,请使用此选项
  ctx.respond 
Request aliases
ctx.header 			Request header object.
ctx.headers 		Set request header object.
ctx.method 			Request method.
ctx.method= 		Set request method, useful for implementing middleware such as methodOverride().
ctx.url 			Get request URL.
ctx.url= 			Set request URL, useful for url rewrites.
ctx.originalUrl 	Get request original URL.
ctx.origin 			Get origin of URL, include protocol and host.
ctx.href 			Get full request URL, include protocol, host and url.
ctx.path 			Get request pathname.
ctx.path= 			Set request pathname and retain query-string when present.
ctx.query  			Get parsed query-string, returning an empty object when no query-string is present. Note that this getter does not support nested parsing.
ctx.query=  		Set query-string to the given object. Note that this setter does not support nested objects.
ctx.querystring  	Get raw query string void of ?.
ctx.querystring= 	Set raw query string.
ctx.host  			Get host (hostname:port) when present. Supports X-Forwarded-Host when app.proxy is true, otherwise Host is used.
ctx.hostname 		Get hostname when present. Supports X-Forwarded-Host when app.proxy is true, otherwise Host is used.
ctx.fresh 			Check if a request cache is "fresh", aka the contents have not changed. This method is for cache negotiation between If-None-Match / ETag, and If-Modified-Since and Last-Modified. It should be referenced after setting one or more of these response headers.
ctx.stale 			Inverse of request.fresh.
ctx.socket			Return the request socket.
ctx.protocol 		Return request protocol, "https" or "http". Supports X-Forwarded-Proto when app.proxy is true.
ctx.secure 			Shorthand for ctx.protocol == "https" to check if a request was issued via TLS.
ctx.ip 				Request remote address. Supports X-Forwarded-For when app.proxy is true.
ctx.ips 			When X-Forwarded-For is present and app.proxy is enabled an array of these ips is returned, ordered from upstream -> downstream. When disabled an empty array is returned.
ctx.subdomains 		Return subdomains as an array.
ctx.is() 			Check if the incoming request contains the "Content-Type" header field, and it contains any of the give mime types. If there is no request body, null is returned. If there is no content type, or the match fails false is returned. Otherwise, it returns the matching content-type.
ctx.accepts() 		Check if the given type(s) is acceptable, returning the best match when true, otherwise false. The type value may be one or more mime type string such as "application/json", the extension name such as "json", or an array ["json", "html", "text/plain"].
ctx.acceptsEncodings() Check if encodings are acceptable, returning the best match when true, otherwise false. Note that you should include identity as one of the encodings!
ctx.acceptsCharsets() Check if charsets are acceptable, returning the best match when true, otherwise false.
ctx.acceptsLanguages() Check if langs are acceptable, returning the best match when true, otherwise false.
ctx.get() 			Return request header.
Response aliases
ctx.body   			Get response body.
ctx.body=  			Set response body
ctx.status 			Get response status. By default, response.status is set to 404 unlike node's res.statusCode which defaults to 200.
ctx.status= 		Set response status via numeric code
ctx.message 		Get response status message. By default, response.message is associated with response.status.
ctx.message= 		Set response status message to the given value.
ctx.length=  		Set response Content-Length to the given value
ctx.length 			Return response Content-Length as a number when present, or deduce from ctx.body when possible, or undefined.
ctx.type= 			Set response Content-Type via mime string or file extension.
ctx.type 			Get response Content-Type void of parameters such as "charset"
ctx.headerSent 		Check if a response header has already been sent. Useful for seeing if the client may be notified on error.
ctx.redirect() 		Perform a [302] redirect to url.
ctx.attachment() 	Set Content-Disposition to "attachment" to signal the client to prompt for download
ctx.set()  			Set several response header fields with an object
ctx.append() 		Append additional header field with value val.
ctx.remove() 		Remove header field.
ctx.lastModified  	Return the Last-Modified header as a Date, if it exists.
ctx.lastModified= 	Set the Last-Modified header as an appropriate UTC string. You can either set it as a Date or date string.
ctx.etag= 			Set the ETag of a response including the wrapped "s. Note that there is no corresponding response.etag getter.
Status code
100 "continue"
101 "switching protocols"
102 "processing"
200 "ok"
201 "created"
202 "accepted"
203 "non-authoritative information"
204 "no content"
205 "reset content"
206 "partial content"
207 "multi-status"
208 "already reported"
226 "im used"
300 "multiple choices"
301 "moved permanently"
302 "found"
303 "see other"
304 "not modified"
305 "use proxy"
307 "temporary redirect"
308 "permanent redirect"
400 "bad request"
401 "unauthorized"
402 "payment required"
403 "forbidden"
404 "not found"
405 "method not allowed"
406 "not acceptable"
407 "proxy authentication required"
408 "request timeout"
409 "conflict"
410 "gone"
411 "length required"
412 "precondition failed"
413 "payload too large"
414 "uri too long"
415 "unsupported media type"
416 "range not satisfiable"
417 "expectation failed"
418 "I'm a teapot"
422 "unprocessable entity"
423 "locked"
424 "failed dependency"
426 "upgrade required"
428 "precondition required"
429 "too many requests"
431 "request header fields too large"
500 "internal server error"
501 "not implemented"
502 "bad gateway"
503 "service unavailable"
504 "gateway timeout"
505 "http version not supported"
506 "variant also negotiates"
507 "insufficient storage"
508 "loop detected"
510 "not extended"
511 "network authentication required"
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值