首先分析一下express的路由都有什么
- 开放静态资源访问
- 对get,post请求进行处理
express是怎么实现的
const express = require("express");
const app = express();
app.static("public")
app.get('/get', (req, res) => {……})
app.post("/post", (req, res) => {……})
先来实现对get以及post请求的处理
1.先定义一个route.js的文件,说白了就是定义一个路由模块
首先在app.js中通过http模块开启一个服务,监听的8081端口
var http = require('http');
http.createServer(function (request, response) {
response.writeHead(200, {'Content-Type': 'text/plain'});
response.end('Hello World');
}).listen(8081);
createServer函数中传入一个回调函数,回调函数有两个参数request存有客户端发来的请求信息,response服务器对客户端的响应,在函数内部通过获取不同的request.url请求路径进行不同的处理和响应,所以我们在route.js中暴露一个app函数,统一处理请求,那么http服务就可以直接写成
const app = require('./route')
http.createServer(app).listen(8081);
在route.js中定义一个函数server,返回一个app函数,这样将变量定义在函数作用域防止污染全局。暴露server执行,返回的就是app这个函数了
route.js
let server = () => {
let app = function (req, res) {
}
return app
}
module.exports = server()
2.处理get,post请求
因为在app.js中注册路由的是app.get/app.post方式的方法,所以此时在app这个函数上定义两个方法,不同的请求方法式处理不同,在server函数中再丁一一个对象G,对象G再定义两个对象分别存储定义的函数
let server = () => {
let G = {
_post: {},
_get: {}
}
let app = function (req, res) {
}
app.get = function (str, cb) {
G._get[str] = cb
}
app.post = function (str, cb) {
G._post[str] = cb
}
return app
}
以app.get()方法为例,我们将app暴露出去,在app.js中引入了这个模块,所以在app.js中就可以调用app.get()方法了,因为是要处理路由,所以app.get函数的第一个参数就是路由,第二个参数就是传入对应的回调函数来处理这个路由的逻辑。app.get方法内部就会对该回调函数进行注册,将str作为_get对象的属性,回调函数就是属性值了。
现在进行一次测试
app.js
这里提前定义一个/login的路由,然后执行app.js文件,在浏览器输入"http://localhost:8081/login",如果页面有“home”打印出来就证明成功了。
const app = require('./route')
var http = require('http');
http.createServer(app).listen(8081);
app.get('/login', (req, res) => {
res.end("home")
})
route.js
因为这里的app函数是作为http.createServer的回调函数,我们不用手动执行,它自己就会执行。在测试的时候事先注册了/login函数,所以在里面判断一下G的_get对象里面有没有这个函数,如果有就执行,所以他一执行就会执行我们为'/login'路由注册的函数,就会给客户端返回字符串“home”
let server = () => {
let G = {
_post: {},
_get: {
}
}
let app = function (req, res) {
if(G._get['/login']){
G._get['/login'](req, res)
}
}
app.get = function (str, cb) {
G._get[str] = cb
}
app.post = function (str, cb) {
G._post[str] = cb
}
return app
}
module.exports = server()
3.实现route.js的app函数的功能
客户端发来的请求可能是post可能是get,而post和get的路由在定义的时候也可能是一样的
如
app.get('/login', (req, res) => {
res.end("home")
})
app.post('/login', (req, res) => {
res.end("home")
})
所以要根据请求方式和路由名称来决定执行哪一个方法
- 首先获取请求的路由名称和请求方法
利用url模块的parse方法获取请求路径中的路由
const url = require('url')
let app = function (req, res) {
// 获取请求的路由,就是如http://localhost:8081/login中的/login
let pathname = url.parse(req.url).pathname;
// 获取请求方法
let method = req.method.toLowerCase();
}
- 根据路由和请求方法决定执行哪个处理函数
let app = function (req, res) {
// 获取请求的路由
let pathname = url.parse(req.url).pathname;
// 获取请求方法,返回的是大写的,这里转成小写了
let method = req.method.toLowerCase();
// 先判断G的_get和_post对象里面有没有对应的路由,如果有向下执行,没有走else
if (G['_' + method][pathname]) {
// 判断请求方法
if (method == "get") {
// get请求方法,执行G._get对象中对应的pathname方法,需要把req和res传过去
G['_' + method][pathname](req, res); //执行方法
} else {
// post方法,post请求参数是以流的形式传递,是一点一点的传输的
let postData = '';
// post参数传输中
req.on('data', (chunk) => {
postData += chunk;
})
// post参数传输完毕,将参数绑定到req.body上,执行G._post对象中对应的函数
req.on('end', () => {
req.body = postData;
G['_' + method][pathname](req, res); //执行方法
})
}
} else {
// 设置响应头,状态码404,文件类型是html,编码字符集是utf-8
res.writeHead(404, { 'Content-Type': 'text/html;charset="utf-8"' });
// 提示页面不存在
res.end('页面不存在');
}
}
这样就算初步完成了
再在res上扩展一个send方法,用来统一设置响应头和响应数据,封装一个changeRes方法,参数传入res
function changeRes(res) {
res.send = (data) => {
res.writeHead(200, {
"Content-Type": "text/html;charset=utf-8"
})
res.end(data)
}
}
在app函数中直接调用一下changeRes方法就行了,传入res
let app = function (req, res) {
//扩展res的方法
changeRes(res);
}
然后在注册路由时候,就可以直接使用了res.send()了,就不用另外再单独设置响应头了
app.get('/login', (req, res) => {
res.send("home")
})
下一节
完整的router.js程序就是
const url = require('url')
function changeRes(res) {
res.send = (data) => {
res.writeHead(200, {
"Content-Type": "text/html;charset=utf-8"
})
res.end(data)
}
}
let server = () => {
let G = {
_post: {},
_get: {
}
}
const app = function (req, res) {
//扩展res的方法
changeRes(res);
let pathname = url.parse(req.url).pathname;
let method = req.method.toLowerCase();
if (G['_' + method][pathname]) {
if (method == "get") {
G['_' + method][pathname](req, res); //执行方法
} else {
let postData = '';
req.on('data', (chunk) => {
postData += chunk;
})
req.on('end', () => {
req.body = postData;
G['_' + method][pathname](req, res);
})
}
} else {
res.writeHead(404, { 'Content-Type': 'text/html;charset="utf-8"' });
res.end('页面不存在');
}
}
app.get = function (str, cb) {
G._get[str] = cb
}
app.post = function (str, cb) {
G._post[str] = cb
}
return app
}
module.exports = server()
网友评论