Koa是由Express团队设计的一种新的Web框架,由 Express 幕后的原班人马打造, 致力于成为 web 应用和 API 开发领域中的一个更小、更富有表现力、更健壮的基石。通过利用异步功能,Koa允许您不再使用回调并大大提高错误处理能力,避免回调地狱问题。 Koa 并没有捆绑任何中间件, 而是提供了一套优雅的方法,帮助您快速而愉快地编写服务端应用程序。
mkdir koa_test
cd koa_test
npm i koa
const Koa = require('koa');
const app = new Koa();
app.use(async ctx => {
ctx.body = 'Hello World';
});
app.listen(3000);
node app.js
浏览器打开http://localhost:3000/
,即可看到Hello World
先安装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);
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
对上一步稍作修改
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
需要安装一个中间件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
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]
一种是调用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
app.on('error', err => {
log.error('server error', err)
});
用于打印请求数据
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
用于发送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)
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
},
}),
);
跨域设置
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 '*' // 本地环境
}
})))
gzip压缩
const compress = require('koa-compress')
app.use(compress({
threshold: 2048,
flush: require("zlib").Z_SYNC_FLUSH
}))
app.listen(...) //监听某个端口
app.use(function) //使用中间件
app.callback()//返回适合http.createServer() 方法以处理请求的回调函数
app.keys = //设置签名的Cookie密钥。
app.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
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.
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.
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"