const Koa = require('koa');
const app = new Koa();
app.listen(8080, () => {
console.log('Server Started...')
})
运行 node server.js
访问 http://localhost:8080/ 浏览器显示 “Not Found”,因为 Koa 还未设置显示内容
Context.response.body 属性规定发送给用户的内容。
const Koa = require('koa');
const app = new Koa();
const main = ctx => {
//main 设置向用户发送内容
ctx.response.body = 'Hello World';
//ctx.response 代表 http response
//ctx.request 代表 http request
}
app.use(main); //使用 app.use 方法加载 main 函数
app.listen(8080, () => {
console.log('Server Started...');
})
ctx.request.accepts 判断客户端需接受数据,ctx.response.type 指定返回类型 (Koa 默认返回类型是text/plain)
//修改mian函数如下
const main = ctx => {
if (ctx.request.accepts('xml')) { //利用 http accepts字段判断客户端可接受数据
ctx.response.type = 'xml'; // ctx.response.type 指定数据类型
ctx.response.body = 'xml';
}else if (ctx.request.accepts('json')) {
ctx.response.type = 'json';
ctx.response.body = {
data : 'json'
};
}else if (ctx.request.accepts('html')) {
ctx.response.type = 'html';
ctx.response.body = 'html'
}else {
ctx.response.type = 'text';
ctx.response.body = 'text';
}
//main 设置向用户发送内容
//ctx.response.body = 'Hello World';
//ctx.response 代表 http response
//ctx.request 代表 http request
}
访问 http://localhost:8080/ 浏览器显示 :
This XML file does not appear to have any style information associated with it. The document tree is shown below.
xml
template.html:
html
修改app.js:
const Koa = require('koa');
const app = new Koa();
const fs = require('fs');
const main = ctx => {
ctx.response.type = 'html';
ctx.response.body = fs.createReadStream('./template.html');
//fs.createReadStream() 从流中读取数据
}
app.use(main);
app.listen(8080);
访问 http://localhost:8080/ 浏览器显示 : html
const Koa = require('koa');
const app = new Koa();
const main = ctx => {
if (ctx.request.path !== '/') {
ctx.response.type = "html";
ctx.response.body = 'Index Page';
}else {
ctx.response.body = "Other";
}
};
app.use(main);
app.listen(8080);
const Koa = require('koa');
const app = new Koa();
const route = require('koa-route');//引入koa-route模块
// const main = ctx => {
// if (ctx.request.path !== '/') {
// ctx.response.type = "html";
// ctx.response.body = 'Index Page';
// }else {
// ctx.response.body = "Other";
// }
// };
const about = ctx => {
ctx.response.type = 'html';
ctx.response.body = 'Index Page';
}
const main = ctx => {
ctx.response.body = 'Index';
}
// app.use(main);
//route.get('path', function); 访问不同路径处理不同的函数
app.use(route.get('/', main));
app.use(route.get('/about', about));
app.listen(8080);
const Koa = require('koa');
const app = new Koa();
const path = require('path');
const serve = require('koa-static');
const main = serve(path.join(__dirname));
//使用 __dirname 是包含源文件的目录的绝对路径
//path.join() Node.js Path模块,此函数是将路径连接在一起,同时考虑操作系统
app.use(main);
app.listen(8080);
const Koa = require('koa');
const app = new Koa();
const route = require('koa-route');
const redirect = ctx => {
ctx.response.redirect('/'); //浏览器将会导向根路由
ctx.response.body = 'Index page';
};
const main = ctx => {
ctx.response.body = 'Index';
}
app.use(route.get('/', main));
app.use(route.get('/redirect', redirect));
app.listen(3000);
const Koa = require('koa');
const app = new Koa();
const main = ctx => {
ctx.response.body = `${Date.now()} ${ctx.request.method} ${ctx.request.url}`;
//显示结果:1550462952434 GET /
}
app.use(main);
app.listen(8080);
将 Logger 功能拆分为独立的函数:
const Koa = require('koa');
const app = new Koa();
const logger = (ctx, next) => {
console.log(`${Date.now()} ${ctx.request.method} ${ctx.request.url}`);
next(); //调用 next 函数
}
const main = ctx => {
ctx.response.body = "Index";
}
app.use(logger);
app.use(main);
app.listen(8080);
const Koa = require('koa');
const app = new Koa();
const one = (ctx, next) => {
console.log('>>one');
next();
console.log('<);
}
const two = (ctx, next) => {
console.log('>>two');
next();
console.log('<);
}
const three = (ctx, next) =>{
console.log('>>three');
next();
console.log('<);
}
app.use(one);
app.use(two);
app.use(three);
app.listen(8080);
输出:
>>one
>>two
>>three
<
最外层的中间件首先执行,调用next函数,把执行权交给下一个中间件,依次执行递交,最内层的中间件最后执行,执行结束后,把执行权交回上一层的中间件,依次执行递交,最外层的中间件收回执行权后,执行next函数后面的代码。
const Koa = require('koa');
const app = new Koa();
const fs = require('fs.promised');
const main = async function (ctx, next) {
//异步操作,改写为 async 函数
ctx.response.type = 'html';
ctx.response.body = await fs.readFile('./template.html', 'utf8');
//fs.readFile() 是异步操作,需改为await fs.readFile()
}
app.use(main);
app.listen(8080);
compose([middleware1, middleware2...])
合成为一个,然后利用 app.use()
加载const Koa = require('koa');
const app = new Koa();
const compose = require('koa-compose');
const logger = (ctx, next) => {
console.log(`${Date.now()} ${ctx.request.method} ${ctx.request.url}`);
next();
}
const main = ctx => {
ctx.response.body = 'Index';
}
const middlewares = compose([logger, main]);
app.use(middlewares);
app.listen(8080);
const main = ctx => {
ctx.throw(400);
}
抛出 Bad Request
ctx.response.status 设置为404,相当于 ctx.throw(404) ,返回404错误
const main = ctx => {
ctx.response.status = 404;
ctx.response.body = 'Page Not Found';
}
const Koa = require('koa');
const app = new Koa();
const handler = async (ctx, next) => {
try {
await next();
}catch (error) {
ctx.response.status = error.statusCode || error.status || 500;
ctx.response.body = {
message: error.message
};
}
};
const main = ctx => {
ctx.throw(500);
};
app.use(handler);
app.use(main);
app.listen(8080);
const Koa = require('koa');
const app = new Koa();
const main = ctx => {
//ctx.response.status = 500;
ctx.throw(500);
}
app.on('error', (err, ctx) => console.error('server error', err))
app.use(main);
app.listen(8080);
但当错误被 try…catch 捕获,就不会触发 error 事件,需要调用 ctx.app.emit() 手动释放 error 事件,才能使监听函数生效
const Koa = require('koa');
const app = new Koa();
const handler = async (ctx, next) => {
try {
await next();
} catch (err) {
ctx.response.status = err.statusCode || err.status || 500;
ctx.response.type = 'html';
ctx.response.body = 'error
';
ctx.app.emit('error', err, ctx); //释放error事件
}
};
const main = ctx => {
ctx.throw(500);
};
app.on('error', function(err) {
console.log('logging error', err.message);
console.log(err);
})
app.use(handler);
app.use(main);
app.listen(8080);
const Koa = require('koa');
const app = new Koa();
const main = ctx => {
const n = Number(ctx.cookies.get('view') || 0) + 1;
//Number() 用于任何数据类型转换成数值
ctx.cookies.set('view', n);
ctx.response.body = n + 'views';
//刷新 cookies 累加
}
app.use(main);
app.listen(8080);
const koaBody = require('koa-body');
const main = async function (ctx) {
const body = ctx.request.body;
if (!body.name) ctx.throw(400);
ctx.body = {
name: body.name
};
}
app.use(koaBody());
app.use(main);
app.listen(8080);
运行文件,另起一个命令行窗口:输入如下命令
localhost:node-koa $ curl -X POST --data "name=Jack" 127.0.0.1:8080
{"name":"Jack"}
localhost:node-koa $ curl -X POST --data "name" 127.0.0.1:8080
Bad Requestlocalhost:node-koa didi$
const Koa = require('koa');
const app = new Koa();
const os = require('os');
const path = require('path');
const koaBody = require('koa-body');
const fs = require('fs');
const main = async function(ctx) {
const tmpdir = os.tmpdir();
//nodejs os操作系统方法 os.tmpdir() 返回一个字符串,表明操作系统的默认临时文件目录
const filePaths = [];
const files = ctx.request.body.files || {};
//ctx.request.body.files 中获取上传的文件内容
//接收到文件后,需将文件保存到目录中,返回一个url给前端
for (let key in files) {
const file = files[key];
const filePath = path.join(tmpdir, file.name);
//path.join() 合成多个路径
const reader = fs.createReadStream(file.path);
const writer = fs.createWriteStream(filePath);
//管道流,一个输出流到输入流的机制,从一个流中获取数据并将数据传递到另一个流中
reader.pipe(writer); //管道流读写操作
filePaths.push(filePath);
}
ctx.body = filePaths;
};
app.use(koaBody({
multipart: true,
formidable: {
maxFileSize: 200*1024*1024 // 设置上传文件大小最大限制,默认2M
}
}));
app.use(main);
app.listen(8080);
运行文件,另起一个命令行窗口:输入如下命令
localhost:node-koa didi$ curl --form upload=@node-http/template.html http://127.0.0.1:8080
[]localhost:node-koa didi$