使用 Node.js express 实现一个简单的 web 服务
这是使用 Node.js express 模块写的一个简单 Web 服务示例,一共三部分:
- 响应http请求
- 路由url
- 读取静态文件响应
新建一个 app.js 文件作为 web 服务的主程序。
响应 http 请求
首先我们引入 http
模块,创建一个 http 服务。
const http = require('http');
const hostname = '127.0.0.1';
const port = 3000;
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World\n');
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
http 的 createServer
方法接收一个函数作为参数。函数有两个参数 request
和 response
,它将用来处理和响应http请求。
示例里response做了简单的三件事:
- res.statusCode=200:设置响应码 statusCode 为 200
- res.setHeader("Content-Type","text/plain"):设置响应头 Content-Type 为 text/plain。
- res.end('Hello World\n'):最后使用 res.end() 方法向请求返回文本。
server.listen
指定服务监听的端口。
这样一个可以用来接收 http 请求和做出简单响应的 web 服务就完成了。
启动web服务:
node app.js
在浏览器输入 http://127.0.0.1:3000
访问服务。
路由 url
对一个 web 服务来说,可能需要接收不同的 url 请求,根据 url 返回对应的请求内容,即路由。
const server = http.createServer((req, res) => {
route(req,res);
});
const ROUTES = [
{path:"",content:"<html><head><meta charset='UTF-8' ></head><body><a href='en'>english</a><br /><a href='cn'>中文</a></body></html>"},
{path:"/en",content:"Welcome to the world of Node.js!"},
{path:"/cn",content:"<html><head><meta charset='UTF-8' ></head><body>欢迎进入Node.js的世界!</body></html>"}
]
function route(req,res) {
let requestUrl = req.url;
const match = requestUrl.match(/\/+$/);
if(match) {
requestUrl = requestUrl.substring(0,match.index);
}
for(let route of ROUTES) { // 查询 route 的 url
if(route.path == requestUrl) {
responseText(res,StatusCode.SUCCESS, route.content);
return;
}
}
responseText(res,StatusCode.NOTFOUND,"Page Not Found.");
}
function responseText(res, statusCode, text) {
res.statusCode = statusCode;
res.setHeader('Content-Type', 'text/html');
res.end(text);
}
现在处理的代码移到 route
函数里,由 route 对 url 处理,根据不同的 url 返回响应的内容。
其中,ROUTES
常量配置了不同 url 对应的返回内容。当在 ROUTES 找不到对应的 url,返回 404。
这样就完成了一个简单的路由。
读取静态文件响应
很明显,上面的路由需要我们配置所有的 url。
在现实项目里,我们会根据不同的 url,然后路由到 url 对应的文件(html,js,css)。这一步我们会修改路由,让路由由 url 转换为对应的文件,然后返回文件内容。
/**
* 此函数根据url路由到对应的文件,并响应文件内容
*/
function routeToFile(req,res) {
let requestUrl = req.url;
const match = requestUrl.match(/\/+$/);
if(match) {
requestUrl = requestUrl.substring(0,match.index);
}
let filePath;
// 如果请求的url没有后缀,返回目录下的index.html
if(path.extname(requestUrl) == '') {
filePath = path.join(wwwRoot,requestUrl, "index.html");
} else {
filePath = path.join(wwwRoot,requestUrl);
}
if(filePath) {
// 响应文件内容
responseFile(res, filePath);
}else {
responseText(res,StatusCode.NOTFOUND, "Page Not Found");
}
}
const fs = require("fs");
function responseFile(res,filePath) {
fs.exists(filePath,(exists) => {
if(exists) {
// 文件存在响应文件内容
const stream = fs.createReadStream(filePath,{flags:"r",encoding:null});
res.statusCode = StatusCode.SUCCESS;
res.setHeader('Content-Type', getContentType(filePath));
stream.pipe(res);
} else {
// 文件不存在返回404
responseText(res,StatusCode.NOTFOUND,"Page Not Found.");
}
});
}
const CONTENT_TYPES = [
{ext:".js",contentType:"text/javascript"},
{ext:".css",contentType:"text/css"},
{ext:".html",contentType:"text/html"}
]
function getContentType(file) {
let ext = path.extname(file);
for(let ct of CONTENT_TYPES) {
if(ct.ext == ext) {
return ct.contentType;
}
}
return "text/html";
}
这样一个简单的 web 服务就完成了。
这只是一个简单的示例,在实际项目中,我们可以使用 express 来作为 web 服务。