肢解 HTTP 服务器构建
更好阅读请戳 这里
1. 最简单的 http 服务器
// server.js
var http = require("http");
http.createServer(function(request, response) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello World");
response.end();
}).listen(8888);
// node server.js
// 打开http://localhost:8888/,你会看到一个写着“Hello World”的网页~
首先我们来看看服务端模式下如何工作:
- 首先需要使用.createServer方法创建一个服务器
- 然后调用.listen方法监听端口
- 之后,每当来了一个客户端请求,创建服务器时传入的回调函数就被调用一次。可以看出,这是一种事件机制
HTTP请求本质上是一个数据流,由请求头(headers)和请求体(body)组成
// 请求头
POST / HTTP/1.1
User-Agent: curl/7.26.0
Host: localhost
Accept: */*
Content-Length: 11
Content-Type: application/x-www-form-urlencoded
// 请求体
Hello World
HTTP请求在发送给服务器时,可以认为是按照从头到尾的顺序一个字节一个字节地以数据流方式发送的。而http模块创建的HTTP服务器在接收到完整的请求头后,就会调用回调函数。在回调函数中,可以使用request对象访问请求头数据并把request对象当作一个只读数据流来访问请求体数据
可修改上述代码
// server.js
var http = require("http");
http.createServer(function(request, response) {
// 读取 requst 数据流
console.log('我是请求方法:', request.method)
console.log('我是请求头:', request.headers)
request.on('data', function (chunk) {
body.push(chunk);
});
request.on('end', function () {
body = Buffer.concat(body);
console.log('我是请求体呀', body.toString());
});
// 处理response
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello World");
response.end();
}).listen(8888);
// node server.js
// 打开http://localhost:8888/,你会看到一个写着“Hello World”的网页~
就这么简单,本文 完~
oh,no
you too young, too simple
2. 肢解代码
var http = require("http")
- 请求(require)Node.js自带的 http 模块,并且把它赋值给 http 变量
createServer
- listen 方法-数值参数指定该 HTTP 服务器监听的端口号
createServer
的参数- 基于事件驱动的回调
- 无论何时我们的服务器收到一个请求,这个函数就会被调用
- 基于事件驱动的回调
请求处理
onRequest() 函数被触发的时候,有两个参数对象
- request
- response
// 发送一个HTTP状态200和HTTP头的内容类型
response.writeHead(200, {"Content-Type": "text/plain"});
// 添加HTTP主体内容
response.write("Hello World");
// 完成响应
response.end();
3. 模块封装
这一步我们把server.js变成一个真正的Node.js模块
函数封装
将我们的脚本封装到一个函数里面,然后导出该封装函数var http = require("http"); function start() {
function onRequest(request, response) {
console.log("Request received.");
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello World");
response.end();
} http.createServer(onRequest).listen(8888);
console.log("Server has started.");
} exports.start = start;
模块引用
// 如主文件名为index.js,写入
var server = require("./server"); server.start();
执行
node index.js
4. 路由
所有请求数据都在 request对象中,数据解析,还需要 url, querystring模块
来,我们试一试找出浏览器的请求路径~
4.1 获取路由
var http = require("http");
var url = require('url')
function start(){
function onRequest(req, res){
var url = url.parse(req.url)
// 打印 url 信息
console.log('server start url', url)
res.writeHead(200, {"content-type": "text/plain"})
res.end()
}
http.createServer(onRequest).listen(8888)
}
exports.start = start
request.url参数打印:
4.2 有路可寻
引入路由处理
- 创建route.js,处理路由信息,在index页面引入该模块,并作为 server 中start 函数的参数执行,
- 解析每一个request,获取其url 路径进行处理
// server.js
var http = require("http");
var url = require('url')
function start(route){
function onRequest(req, res){
var pathname = url.parse(req.url).pathname
route(pathname)
res.writeHead(200, {"content-type": "text/plain"})
res.end()
}
http.createServer(onRequest).listen(8888)
}
exports.start = start
// route.js
function route(pathname){
console.log('route', pathname)
}
exports.route = route
// index.js 引入route
var server = require('./server')
var router = require('./route')
server.start(router.route)
以上代码我们实现了有路可寻
为了避免多重的 if..else..,我们通过对象传递一系列请求
首先创建一个 requestManager 模块,导出多个处理函数
创建 managers 对象:映射不同路由的处理方法
将路由与函数的映射关系作为参数传递给 server
server 中调用 route 的处理结果
// requestManager.js
function start(){
console.log('route-----start')
return 'hello start'
}
function next(){
console.log('route-----next')
return 'hello next'
}
exports.start = start
exports.next = next
// index.js
var server = require('./readfile')
var router = require('./route')
var requestManager = require('./requestManager') var managers = []
managers['/'] = requestManager.start
managers['/start'] = requestManager.start
managers['/next'] = requestManager.next server.start(router.route, managers) // http://localhost:8888/start, 浏览器会输出“hello start”
// http://localhost:8888/next 会输出“hello next”
// http://localhost:8888/chaoran 会输出“404”。
manager :每一个路由提供对应的处理函数
// server.js
var http = require("http");
var url = require('url') function start(route, manager){
function onRequest(req, res){
var pathname = url.parse(req.url).pathname
console.log('server request for', pathname)
var content = route(pathname, manager)
res.writeHead(200, {"content-type": "text/plain"})
res.write(content)
res.end()
}
http.createServer(onRequest).listen(8888)
} exports.start = start
取出managers 中的路由事件进行处理
// route.js
function route(pathname, managers){
console.log('rrr', pathname)
if(typeof managers[pathname] == 'function'){
return managers[pathname]() }else {
console.log('managers no found')
return ''
}
} exports.route = route
好啦,用是能用的,就是偶尔会挂 ( ﹁ ﹁ ) ~→
至于node中的并行及如何实现非阻塞,下次我们结合实例来学习~
参考:
最新文章
- 总结C#保留小数位数及百分号处理
- 隐式调用 Intent 大全, 很全
- 我理解的Android加载器
- 本地的手机号码归属地查询-oracle数据
- Linux makefile教程之make运行八[转]
- React学习笔记(三) 组件传值
- linux创建交换分区
- test在博客中嵌入实例代码
- 虚拟机搭建hadoop环境
- 201521123045 《Java程序设计》 第十三周学习总结
- BlockingQueue<;>; 队列的作用
- mysql数据库第三弹
- Swift基础之自定义PUSH和POP跳转动画
- 阿里云弹性容器实例产品 ECI ——云原生时代的基础设施
- ssh远程登录出现Host key verification failed.解决办法
- 【Python】easygui小甲鱼
- tcp_tw_recycle和tcp_timestamps导致connect失败问题
- 160229-01、web页面常用功能js实现
- Codeforces Round #342 (Div. 2) C
- 【研究】ms17-010永恒之蓝漏洞复现
热门文章
- Flask 学习笔记(二):RESTful API
- spring环境搭建(简单实例)
- 安全警告——“Windows已经阻止此软件因为无法验证发行者”解决办法
- [IOI2000][POJ1160]Post office
- NOIP2010 引水入城 贪心+DFS
- “CNKI 中国知网 PDF 全文下载”油猴脚本在线安装地址
- egrep对于conf文件中去掉#注释,排除无用项
- Spring学习--泛型依赖注入
- Sencha Touch2 -- 11.1:定义具有关联关系的模型
- AQS同步组件及ReentrantLock和synchronized的区别