背景说明
HTTP模块,一个轻量的,基于异步I/O的,以及事件驱动的 Web 服务器。
url模块,用于生成和解析URL,使用前,先加载。
querystring模块,http请求数据进行解析,提供4个方法:1、querystring.parse,将一个字符串反序列化为一个对象;2、querystring.stringify,将一个对象序列化成一个字符串,与querystring.parse是相对的;3、querystring.escape,escape可使传入的字符串进行编码;4、querystring.unescape,unescape方法可将含有%的字符串进行解码。
util模块,promisify(),Node.js内置的util模块的promisify()方法,将基于回调的函数转换为基于Promise的函数。可以将Promise链和async/await与基于回调的API结合使用。
工程结构
工程
│ app.js
│ package.json
│
├─data
│ user.json
│
├─router
│ index.js
│
├─static
│ login.html
工程代码
app.js
const http = require('http');
const url = require('url');
const router = require('./router/index');
const app = http.createServer((req, res) => {
// 当前请求方法
const method = req.method.toUpperCase();
console.log("当前请求方法:" + method);
// 当前请求路径
const { pathname } = url.parse(req.url);
console.log("当前请求方法:" + pathname);
// GET处理
if (method === 'GET') {
switch (pathname) {
case '/':
router.index(req, res)
break;
case '/index':
router.index(req, res)
break;
case '/json':
router.json(req, res)
break;
case '/query':
router.query(req, res)
break;
}
}
// POST处理
if (method === 'POST') {
switch (pathname) {
case '/login':
router.login(req, res)
break;
case '/register':
router.register(req, res)
break;
}
}
});
app.listen(3000, () => {
console.log('服务3000已启动.')
});
package.json
{
"name": "demo",
"version": "1.0.0",
"description": "",
"main": "app.js",
"scripts": {
"start":"node app.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
router/index.js
const url = require('url');
const path = require('path');
const fs = require('fs');
const qs = require('querystring');
const { promisify } = require('util');
const readFile = promisify(fs.readFile);
const writeFile = promisify(fs.writeFile);
module.exports = {
// 首页
index(req, res) {
let appDir = path.dirname(require.main.filename);
console.log("appDir=" + appDir + ", __dirname=" + __dirname);
//读取静态文件并生成流
fs.readFile(appDir + '/static/login.html', function (err, data) {
if (err) {
res.writeHead(404, { 'Content-Type': 'text/html;charset=utf-8' });
res.write("页面不存在!404");
res.end();
} else {
res.writeHead(200, { 'Content-Type': 'text/html;charset=utf-8' });
res.write(data.toString());
res.end();
}
});
},
json(req, res) {
res.status = 200;
res.setHeader('Content-Type', 'application/json');
// res.writeHead(200, { 'Content-Type': 'application/json;charset=utf-8' });
res.end(JSON.stringify({
msg: 'json'
}));
},
// 查询
query(req, res) {
const { query } = url.parse(req.url, true);
res.status = 200
res.setHeader('Content-Type', 'application/json')
res.end(JSON.stringify(query || {}))
},
// 登录页面
login(req, res) {
let array = [];
req.on('data', (chunk) => {
array.push(chunk);
})
req.on('end', async () => {
let params = Buffer.concat(array).toString();
params = qs.unescape(params);
console.log("params>>>>>>" + params);
let paramArray = params.split("&");
let loginData = {};
if (paramArray && paramArray.length > 0) {
paramArray.forEach((item, index) => {
let strs = item.split("=");
if (strs.length >= 2) {
loginData[strs[0]] = strs[1];
}
});
}
console.log("loginData>>>>>>" + loginData);
try {
const appDir = path.dirname(require.main.filename);
const jsonPath = appDir + "/data/user.json";
let jsonData = await readFile(jsonPath, { encoding: 'utf8' });
console.log("jsonData>>>>>>" + jsonData);
console.log("jsonData>>>>>>" + JSON.parse(jsonData || '[]'));
let result = JSON.parse(jsonData || '[]').some(item => {
console.log("loginData.username=" + loginData.username);
console.log("item.username=" + item.username);
console.log("loginData.password=" + loginData.password);
console.log("item.password=" + item.password);
return item.username === loginData.username && item.password === loginData.password
})
if (result) {
res.status = 200;
res.setHeader('Content-Type', 'application/json')
res.end(JSON.stringify({
msg: '登录成功'
}))
} else {
res.status = 400;
res.setHeader('Content-Type', 'application/json')
res.end(JSON.stringify({
msg: '登录失败'
}))
}
} catch (e) {
res.status = 500;
res.setHeader('Content-Type', 'application/json')
res.end(JSON.stringify({
msg: '登录错误',
err: e.message
}))
}
})
},
register(req, res) {
let array = [];
req.on('data', (chunk) => {
array.push(chunk);
})
req.on('end', async () => {
console.log("array.length", array.length);
console.log("array", array);
let params = Buffer.concat(array).toString();
// params username=%E7%94%A8%E6%88%B7&password=mima
console.log("params", params);
// params username=用户&password=mima
params = qs.unescape(params)
console.log("params", params);
//
let paramArray = params.split("&");
let objectArray = [];
if (paramArray && paramArray.length > 0) {
paramArray.forEach((item, index) => {
let strs = item.split("=");
if (strs.length >= 2) {
let obj = {};
obj[strs[0]] = strs[1];
objectArray.push(obj);
}
});
}
console.log("objectArray", objectArray);
// 注册成功
res.status = 200;
res.setHeader('Content-Type', 'application/json')
res.end(JSON.stringify({
msg: '注册成功',
data: objectArray
}));
});
}
}
static/login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户登录</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.6.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container " style="width:600px;">
<span>
<h1>用户登录</h1>
</span>
<form method="post" action="/login">
<div class="form-group">
<label for="username">用户名:</label>
<input id="username" name="username" type="text" class="form-control" value="" />
</div>
<div class="form-group">
<label for="password">密码:</label>
<input id="password" name="password" type="password" class="form-control" value="" />
</div>
<button type="reset" class="btn btn-secondary">取消</button>
<button type="submit" class="btn btn-danger">登录</button>
</form>
</div>
</body>
</html>
data/user.json
[
{
"id": "1",
"username": "admin",
"password": "admin123",
"mobile": null,
"email": null,
"jobNumber": null,
"nickname": null,
"portraitId": null,
"portraitAddress": null,
"workPost": null,
"workRole": null,
"sorted": 1,
"status": 1,
"type": "1",
"name": "用户",
"idNumber": null,
"remarks": null,
"lockType": 1,
"startTime": null,
"expireTime": null,
"orgId": "1501744401741774848",
"orgName": "所属机构",
"deptId": "1526411740659580928",
"deptName": "所属部门",
"orgLevel": 3,
"orgTree": "1497055230288723968,1501744401741774848,1526411740659580928",
"domainId": "1497055230288723968",
"roleId": null,
"hisUserId": null,
"version": 0,
"createUid": 0,
"belongOrg": {
"id": "1501744401741774848",
"name": "所属机构",
"code": "S2333",
"type": 1,
"status": 1,
"parentId": "1497055230288723968",
"treeLevel": 2,
"parentFullPath": "1497055230288723968",
"sorted": 1,
"remarks": "",
"belongOrgId": "1497055230288723968",
"domainId": "1497055230288723968",
"logicalDeleted": 0,
"createUid": "1",
"createUser": "super",
"createTime": "2022-03-10T02:19:01.000+00:00",
"modifiedUser": null,
"modifiedTime": null,
"deletedUser": null,
"deletedTime": null,
"children": null,
"parentOrg": null,
"fullPath": "1497055230288723968,1501744401741774848"
},
"belongDept": {
"id": "1526411740659580928",
"name": "所属部门",
"code": "B121212",
"type": 4,
"status": 1,
"parentId": "1501744401741774848",
"treeLevel": 3,
"parentFullPath": "1497055230288723968,1501744401741774848",
"sorted": 2,
"remarks": "",
"belongOrgId": "1501744401741774848",
"domainId": "1497055230288723968",
"logicalDeleted": 0,
"createUid": "1",
"createUser": "super",
"createTime": "2022-05-17T03:58:13.000+00:00",
"modifiedUser": null,
"modifiedTime": null,
"deletedUser": null,
"deletedTime": null,
"children": null,
"parentOrg": null,
"fullPath": "1497055230288723968,1501744401741774848,1526411740659580928"
}
}
]