简单的 demo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
| const express = require("express");
const bodyParser = require("body-parser");
const morgan = require("morgan");
let jsonParser = bodyParser.json({ extended: false });
const app = express();
const unknownEndpoint = (request, response) => { response.status(404).send({ error: "unknown endpoint" }); };
app.use(unknownEndpoint);
app.use(express.json());
morgan.token("body", function (req, res) { return JSON.stringify(req.body); });
morgan.format( "format", ":method :url :status :res[content-length] - :response-time ms :body" );
app.use(morgan("format"));
let persons = [ { id: 1, name: "Arto Hellas", number: "040-123456", }, { id: 2, name: "Ada Lovelace", number: "39-44-5323523", }, { id: 3, name: "Dan Abramov", number: "12-43-234345", }, { id: 4, name: "Mary Poppendieck", number: "39-23-6423122", }, ];
app.get("/api/persons", (request, response) => { response.json(persons); });
app.get("/info", (request, response) => { const peopleNum = persons.length; response.send( `<p>Phonebook has info for ${peopleNum} people</p><p>${new Date()}</p>` ); });
app.get("/api/persons/:id", (request, response) => { const id = Number(request.params.id); const person = persons.find((i) => i.id === id); if (person) { response.json(person); } else { response.status(404).end(); } });
app.delete("/api/persons/:id", (request, response) => { const id = Number(request.params.id); persons = persons.filter((i) => i.id !== id); response.status(204).send({ msg: "delete successful" }).end(); });
app.post("/api/persons", jsonParser, (request, response) => { const person = request.body; if (!person.name) { response.status(400).send({ error: "please provide name" }); return; } if (!person.number) { response.status(400).send({ error: "please provide number" }); return; } const isExistName = persons.find((i) => i.name === person.name); if (isExistName) { response.status(400).send({ error: "name must be unique" }); return; } person.id = Math.round(Math.random() * (1000 - 100000000)) + 100000000;
persons = persons.concat(person);
response.json(person); });
app.listen(3001);
|
中间件 (Middleware)
中间件是可以用来处理 request 和 response 对象的函数。
我们之前使用的 json-parser 从请求中获取原始数据,这些数据存储在 request 对象中,将其解析为一个 JavaScript 对象,并将其作为一个新的属性 body 分配给 request 对象。
让我们来实现我们自己的中间件,它可以打印出发送到服务器的每个请求的信息。
中间件是一个接收三个参数的函数
1 2 3 4 5 6 7
| const requestLogger = (request, response, next) => { console.log("Method:", request.method); console.log("Path: ", request.path); console.log("Body: ", request.body); console.log("---"); next(); };
|
在函数体的最后,调用作为参数传递的 next 函数。这个next 函数将控制权交给下一个中间件。
中间件是这样被使用的。
中间件函数的调用顺序是它们被 Express 服务器对象的 use 方法所使用的顺序。请注意,json-parser 是在 requestLogger 中间件之前被使用的,因为否则在执行记录器的时候,request.body 将不会被初始化。
如果我们想让中间件函数在路由事件处理程序被调用前执行,那么就必须在路由之前使用这些中间件函数。也有一些情况,我们想在路由之后定义中间件函数。在实践中,这意味着我们要定义的中间件函数只有在没有路由处理 HTTP 请求时才会被调用。
让我们在路由之后添加以下中间件,用于捕捉向不存在的路由发出的请求。对于这些请求,中间件将返回一个 JSON 格式的错误信息。
1 2 3 4 5
| const unknownEndpoint = (request, response) => { response.status(404).send({ error: 'unknown endpoint' }) }
app.use(unknownEndpoint)
|
morgan
github
注意,即使在控制台中记录数据也是危险的,因为它可能包含敏感数据,并可能违反当地的隐私法(如欧盟的 GDPR)或商业标准。
自定义日志格式
1 2 3 4
| morgan.format( "format", ":method :url :status :res[content-length] - :response-time ms :body" );
|
自定义 token
1 2 3
| morgan.token("body", function (req, res) { return JSON.stringify(req.body); });
|
控制台运行结果
1
| POST /api/persons 400 31 - 0.621 ms {"name":"aapls","number":"0asd20-8780"}
|
mongoose
- 在 https://cloud.mongodb.com/ 上建好 project 后,本地连接上(这个步骤不记得的可以上网搜索)
- 安装 mongoose