NodeJs-Express

简单的 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");
//HTTP请求体解析中间件
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 函数将控制权交给下一个中间件。

中间件是这样被使用的。

1
app.use(requestLogger)

中间件函数的调用顺序是它们被 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

  1. https://cloud.mongodb.com/ 上建好 project 后,本地连接上(这个步骤不记得的可以上网搜索)
  2. 安装 mongoose
1
npm install mongoose