HTTP服务器创建与请求响应处理
写作思路: 先讲讲每个node.js模块基础知识,再附带完整代码。本人刚入门,了解到node.js在前端还是需要了解一些的。刷了下网课初学node.js,有些地方不对的希望大佬可以指出,欢迎掘友一起讨论学习
创建HTTP服务器
const http = require('http');
// 创建服务器实例,回调函数接收请求对象request,响应对象response
const server = http.createServer((request, response) => {
// 处理请求和响应的逻辑
});
设置响应头
//设置响应头,指定响应的内容类型为HTML,并设置字符编码为UTF-8
response.setHeader('content-type', 'text/html;charset=utf-8');
处理不同类型的请求
//从请求对象中解构出请求方法(如GET、POST等)。
let { method } = request;
//使用URL对象解析url,提取路径部分
let { pathname } = new URL(request.url, `http://127.0.0.1`);
//处理不同的请求路径
if (method === 'GET' && pathname === '/login') {
response.end('<h1>登录页面</h1>');
} else if (method === 'GET' && pathname === '/register') {
response.end('<h1>注册页面</h1>');
} else {
response.end('<h1>404 Not Found</h1>');
}
监听端口并启动服务器
server.listen(9000, () => {
console.log('9000端口启动成功');
});
HTTP模块完整代码:
const http = require('http');
const fs = require('fs');
const path = require('path');
// 创建服务器实例
const server = http.createServer((request, response) => {
// 设置响应头,指定内容类型为HTML,并设置字符编码为UTF-8
response.setHeader('content-type', 'text/html;charset=utf-8');
// 解析请求方法和路径
const { method } = request;
const { pathname } = new URL(request.url, `http://127.0.0.1`);
// 构建文件路径
const root = __dirname + '/page';
const filePath = path.join(root, pathname);
// 异步读取文件
fs.readFile(filePath, (err, data) => {
if (err) {
// 错误处理
if (err.code === 'ENOENT') {
// 文件不存在,返回404页面
response.writeHead(404, { 'Content-Type': 'text/html' });
response.end('<h1>404 Not Found</h1>');
} else {
// 其他错误,返回500页面
response.writeHead(500, { 'Content-Type': 'text/html' });
response.end('<h1>500 Internal Server Error</h1>');
}
} else {
// 成功处理
response.end(data);
}
});
});
// 监听端口并启动服务器
server.listen(9000, () => {
console.log('9000端口启动成功');
});
文件读写操作
导入必要的模块
const fs = require('fs');
const path = require('path');
构建文件路径
// 获取路径
let { pathname } = new URL(request.url, 'http://127.0.0.1');
let root = __dirname + '/page';
let filePath = root + pathname;
异步读取文件
fs.readFile(filePath, (err, data) => {
if (err) {
// 错误处理
return;
}
// 成功处理
response.end(data);
});
错误处理
设置状态码和响应体
response.statusCode = 404;
response.end('404 Not Found');
根据错误代码处理不同的错误情况
switch (err.code) {
case 'ENOENT':
response.statusCode = 404;
response.end('404 Not Found');
break;
case 'EISDIR':
response.statusCode = 403;
response.end('403 Forbidden');
break;
default:
response.statusCode = 500;
response.end('500 Internal Server Error');
break;
}
完整代码
const http = require('http');
const fs = require('fs');
const path = require('path');
// 创建服务器实例
const server = http.createServer((request, response) => {
// 设置响应头,指定内容类型为HTML,并设置字符编码为UTF-8
response.setHeader('content-type', 'text/html;charset=utf-8');
// 解析请求方法和路径
const { method } = request;
const { pathname } = new URL(request.url, 'http://127.0.0.1');
// 构建文件路径
const root = __dirname + '/page';
const filePath = path.join(root, pathname);
// 异步读取文件
fs.readFile(filePath, (err, data) => {
if (err) {
// 错误处理
switch (err.code) {
case 'ENOENT':
// 文件不存在,返回404页面
response.statusCode = 404;
response.end('404 Not Found');
break;
case 'EISDIR':
// 请求的是目录,返回403页面
response.statusCode = 403;
response.end('403 Forbidden');
break;
default:
// 其他错误,返回500页面
response.statusCode = 500;
response.end('500 Internal Server Error');
break;
}
} else {
// 成功处理
response.end(data);
}
});
});
// 监听端口并启动服务器
server.listen(9000, () => {
console.log('9000端口启动成功');
});
MIME类型设置
获取文件后缀名
let ext = path.extname(filePath).slice(1);
设置响应头的Content-Type
let type = mimes[ext]; // 假设mimes是一个对象,存储了文件扩展名与MIME类型的映射
if (type) {
response.setHeader('Content-Type', type + ';charset=utf-8');
} else {
response.setHeader('Content-Type', 'application/octet-stream');
}
获取请求体
表单提交:创建一个HTML页面,其中包含一个POST方法提交的表单。此表单可以用于向后端发送数据,下面创建一个表单实例。
使用body-parser中间件
body-parser是一个Node.js中间件,用于解析HTTP请求体,特别是对于JSON格式的数据非常有用。- 安装:可以通过运行
npm install body-parser来安装。 - 使用:在Express应用中引入并配置
body-parser,以便能够处理JSON数据。app.use(bodyParser.json());,这段代码在处理任何代码前,先使用body-parser来解析请求体中的JSON数据,再将解析的数据存在req.body对象中。
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
// 解析JSON格式的请求体
app.use(bodyParser.json());
app.post('/submit-form', (req, res) => {
// 访问请求体中的数据
console.log(req.body);
res.send('Form submitted!');
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
静态资源中间件
const express = require('express');
// 创建应用对象
const APP = express();
// 静态资源中间件
APP.use(express.static(__dirname + '/public'));
// 创建路由
APP.get('/home', checkCodeMiddleware, (req, res) => {
res.send('我才是首页~~~');
});
// 启动服务器
APP.listen(3000, () => {
console.log('服务器启动成功');
});
静态资源路径优先于路由路径,最先匹配的路径会被响应。
APP.get('/home', checkCodeMiddleware, (req, res) => { ... }); 这段代码定义一个GET请求路由,当访问/home路径时,首先执行checkCodeMiddleware中间件,然后返回“我才是首页~~~”。
防盗链
- 原理:通过检查HTTP请求头部的
Referer字段来确定请求的来源。如果不是预期的来源,则拒绝服务。 - 实现:在Express应用中添加中间件,用于验证请求的Referer字段
- 检查
Referer字段是否存在且合法。 - 如果
Referer字段中的主机名不在白名单内,返回404错误。 - 白名单就是允许访问资源的主机列表
- 示例代码:
- 检查
const express = require('express');
const app = express();
// 设置防盗链中间件
app.use((req, res, next) => {
const referer = req.get('Referer');
//对含有发起请求的页面URL进行进一步处理
if (referer) {
const url = new URL(referer);
//定义了一个数组allowedHosts,其中包含了允许访问的主机名或IP地址
const allowedHosts = ['127.0.0.1', 'localhost'];
//如果不在允许类别,返回404
if (!allowedHosts.includes(url.hostname)) {
res.status(404).send('<h1>404 Not Found</h1>');
return;
}
}
//在主机列表,next()继续处理请求
next();
});
// 设置静态资源目录
app.use(express.static(__dirname + '/public'));
app.listen(3000, () => {
console.log('服务器启动成功');
});
模块化
- 定义路由:在Express中,可以通过创建路由对象来组织和管理路由逻辑。
- 创建路由文件(如
routes.js),并在其中定义路由。 - 在主应用文件中加载路由模块,并将其挂载到特定路径上。
- 示例代码:
- 创建路由文件(如
// routes.js 创建路由
const express = require('express');
const router = express.Router();
router.get('/search', (req, res) => {
res.send('搜索结果页面');
});
router.get('/home', (req, res) => {
res.send('首页页面');
});
module.exports = router;
// app.js 主应用文件加载routes 路由
const express = require('express');
const app = express();
const routes = require('./routes');//导入routes文件
//将路由模块挂载到根路径/上,由模块中的路径是相对于挂载路径
app.use('/', routes);
app.listen(3000, () => {
console.log('服务器启动成功');
});
EJS模板引擎
- 介绍:EJS(Embedded JavaScript)是一种简单的JavaScript模板语言,允许开发者将JavaScript代码嵌入到HTML文档中。
- 使用:
在Express应用中配置EJS作为视图引擎,然后可以在路由处理器中渲染EJS模板文件。- 安装:
npm install ejs - 配置:在Express应用中设置视图引擎为EJS。
- 渲染模板:使用
res.render()方法来渲染EJS模板文件。
- 安装:
const express = require('express');
const app = express();
// 设置视图引擎为EJS
app.set('view engine', 'ejs');
// 设置视图目录(可选,如果视图文件在默认的views目录下,可以省略)
app.set('views', __dirname + '/views');
// 渲染名为index视图模版,传递对象 { title: '主页' }作为局部变量,传递到HTML页面
//注意:express默认在view目录下查找index.ejs
app.get('/', (req, res) => {
res.render('index', { title: '主页' });
});
app.listen(3000, () => {
console.log('服务器启动成功');
});
//view文件夹下index.js文件
<!-- views/index.ejs -->
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
</head>
<body>
<h1><%= title %></h1>
<p>欢迎来到主页!</p>
</body>
</html>
全局变量与中间件
const express = require('express');
const fs = require('fs');
const path = require('path');
// 创建应用对象
const APP = express();
// 全局中间件,该中间件会在所有路由处理之前执行
APP.use((req, res, next) => {
// 解构url,id,记录日志,保存到access.log文件中
const { url, id } = req;
//将请求的URL和ID追加到`access.log`文件中
fs.appendFileSync(path.resolve(__dirname, './access.log'), `${url} ${id}\n`);
console.log(url, id);
// 调用后续中间件
next();
});
// 启动服务器
APP.listen(3000, () => {
console.log('服务器启动成功');
});
路由中间件
const express = require('express');
const fs = require('fs');
const path = require('path');
// 创建应用对象
const APP = express();
// 路由中间件
let checkCodeMiddleware = (req, res, next) => {
// 获取客户端提交的验证码
let code = req.query.code;
if (code === '321') {
next(); // 执行后续回调
} else {
res.send('验证码错误');
}
};
// 使用app.use注册路由中间件,可以处理所有类型的HTTP请求(GET、POST、PUT等)
APP.use(checkCodeMiddleware);
// 创建路由
APP.get('/home', checkCodeMiddleware, (req, res) => {
res.send('前台首页');
});
// 404页面中间件
APP.all('*', (req, res) => {
res.send("<h1>404 页面不存在</h1>");
});
// 启动服务器
APP.listen(3000, () => {
console.log('服务器启动成功');
});