http 模块
http
模块用于 HTTP 通信。
http.Server
http.Server
属性指向一个类,表示 Web 服务器实例。
这个类继承了net.Server
,而net.Server
继承了 EventEmitter 接口,因此可以使用server.on()
方法监听事情。最重要的一个事件是request
,表示收到 HTTP 请求。
server.listen()
方法用于启动 Web 服务。这个方法需要指定监听的端口,以及一个回调函数(启动后要做什么)。
http.createServer()
http.createServer()
方法用于创建一个 Web 服务器,它的返回值就是一个http.Server
实例。
const { createServer } = require('http');
// 指定端口
const PORT = process.env.PORT || 8080;
const server = createServer();
server.on('request', (request, response) => {
response.end('Hello, world!');
});
server.listen(PORT, () => {
console.log(`starting server at port ${PORT}`);
});
request
事件的回调函数,可以作为createServer()
方法的参数。因此,上面的代码也可以写成下面的样子。
const { createServer } = require('http');
const PORT = process.env.PORT || 8080;
const server = createServer((request, response) => {
response.end('Hello, world!');
}).listen(PORT, () => {
console.log(`starting server at port ${PORT}`);
});
response 对象
HTTP 请求和回应都是数据流(stream),request
是只读数据流,response
是可写数据流。
response.write()
方法表示依次向 HTTP 回应写入内容。
response.end()
方法表示写入数据以后,关闭response
数据流。
const { createServer } = require('http');
createServer((request, response) => {
// 等同于 response.end('Hello, world!')
response.write('Hello');
response.write(', ');
response.write('World!');
response.end();
}).listen(8080);
注意,response.end()
是必需的,而且必须写在最后,否则 Node 不会关闭请求。
如果要向客户端发送文件,也可以写成数据流。
const { createReadStream } = require('fs');
const { createServer } = require('http');
createServer((request, response) => {
createReadStream(__filename).pipe(response);
}).listen(8080);
上面代码会将这个脚本代码,发送给客户端。这时不用写response.end()
方法,因为pipe()
方法会在发送结束后,自动关闭数据流。
response.setHeader()
方法用于设置返回的头信息。
const { createServer } = require('http');
createServer((req, res) => {
res.setHeader('content-type', 'application/json');
res.end(JSON.stringify({ foo: 'bar' }));
}).listen(8080);
下面是设置 Cookie 的例子。
const { createServer } = require('http');
createServer((req, res) => {
res.setHeader(
'Set-Cookie',
['myCookie=myValue'],
['mySecondCookie=mySecondValue']
);
res.end(`Your cookies are: ${req.headers.cookie}`);
}).listen(8080);
response.writeHead()
方法与response.setHeader()
类似,但是优先级更高。它可以设置返回的 HTTP 状态码,第一个参数是状态码,第二个参数是状态说明。
const { createServer } = require('http');
createServer((req, res) => {
res.writeHead(204, 'My Custom Message');
res.end();
}).listen(8080);
request 对象
request.headers
属性返回一个对象,包含了 HTTP 请求的头信息。该对象的键名是头信息的字段名,键值是头信息的字段值。
const { createServer } = require("http");
createServer((request, response) => {
const languages = request.headers['accept-language'];
response.end(languages);
}).listen(8080);
上面代码返回 HTTP 请求的头信息accept-language
。
request.url
属性返回浏览器请求的路径,可以基于这个属性做一个简单的路由。
const { createServer } = require('http');
createServer((req, res) => {
switch (req.url) {
case '/':
res.end('You are on the main page!');
break;
case '/about':
res.end('You are on about page!');
break;
default:
res.statusCode = 404;
res.end('Page not found!');
}
}).listen(8080);
获取查询字符串,可以用 Node 内置的url
模块解析request.url
属性。
const { createServer } = require('http');
createServer((req, res) => {
const { query } = require('url').parse(req.url, true);
if (query.name) {
res.end(`You requested parameter name with value ${query.name}`);
} else {
res.end('Hello!');
}
}).listen(8080);
request.method
属性返回浏览器请求的方法。
const { createServer } = require('http');
createServer((req, res) => {
if (req.method === 'GET') {
return res.end('List of data');
} else if (req.method === 'POST') {
return res.end('success');
} else {
res.statusCode(400);
return res.end('Unsupported method');
}
}).listen(8080);
POST 请求发送的数据体是一个数据流(stream),可以用request.on()
方法监听data
事件,累加数据流的每一部分;监听end
事件,得到数据流接收结束的通知。
const { createServer } = require('http');
createServer((req, res) => {
if (req.method === 'POST') {
let data = '';
req.on('data', chunk => {
data += chunk;
});
req.on('end', () => {
try {
const requestData = JSON.parse(data);
requestData.ourMessage = 'success';
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify(requestData));
} catch (e) {
res.statusCode = 400;
res.end('Invalid JSON');
}
});
} else {
res.statusCode = 400;
res.end('Unsupported method, please POST a JSON object');
}
}).listen(8080);