Node.js Web 模块
1.创建 Web 服务器
创建 Web 服务器需要用到http模块
使用http模块搭建一个基本的服务器:
步骤一:引入http模块
步骤二:创建服务对象 createServer(cb)
步骤三:设置路由,根据路径给客户端响应相关的数据
步骤四:开启服务
//引入http模块
const http = require('http')
//创建服务对象
let server = http.createServer((req,res) =>{
if(req.url === "/"){
//设置要响应的数据
res.write("这是首页")
//结束此次响应
res.end()
}
})
//开启服务
server.listen(80,"127.0.0.1",function(){
console.log("Server running at http://127.0.0.1:80/")
})
2.向客户端响应数据
向客户端响应数据要做到3点:
(1)设置头部信息,告知告知浏览器以何种编码解析数据 res.setHeader()
(2)设置响应的数据主体 res.write()
(3)结束此次请求。res.end()
注意:没有设置正确的contetn-type,浏览器就无法正确的解析相关数据
注意:res.write()可以多次发送数据,但是它只是把数据放入队列中,需要配合res.end()才能正常接收数据并且结束此次请求
注意:响应每个请求时都要加上res.end(),告知浏览器此次请求的相应已结束。不然浏览器会一直转圈圈。
res.end()本身也可以响应数据,但是数据类型只能是字符串和Buffer,其他类型的数据会报错。
//没有contetn-type,默认中文会乱码
app.get("/",function(req,res){
res.write("你好")
res.end()
})
//没有res.end() 客户端一直转圈,且接收不到res.write响应的数据
app.get("/",function(req,res){
res.write("hello")
res.write(" world")
})
正确的姿势:
//引入http模块
const http = require('http')
//创建服务对象
let server = http.createServer((req,res) =>{
if(req.url === "/"){
//设置头部信息
res.setHeader("Content-Type","text/html;charset=utf-8")
//设置要响应的数据
res.write("<h1>这是首页</h1>")
res.write("<h1>Node.js Web模块</h1>")
//结束此次响应
res.end()
}
})
//开启服务
server.listen(80,"127.0.0.1",function(){
console.log("Server running at http://127.0.0.1:80/")
})
3.req和res对象
创建http服务对象时,需要传入一个函数,用于处理用户的请求(判断请求地址和返回数据等)。这个传入的函数自带两个参数:req和res
req包含用户请求的信息,常用的有:
- req.url:请求路径(包含query参数) 例如www.xxx.com/yyy => /yyy
- req.method:客户端请求使用的方法(get,post...)
- req.headers:返回所有的请求报文头,例如host/User-Agent/HostCookie等
res用来向客户端响应数据,常用的有:
- res.writeHead():向请求发送响应头,只能在消息上调用一次,即使代码没有写,系统默认也会调用它。
res.writeHead(200, { 'Content-Type': 'text/plain' })
- res.setHeader():设置响应头,例如
res.setHeader('Content-Type', 'text/html')
- res.write():该方法发送一块响应主体。 可以多次调用该方法以提供连续的响应主体片段
res.write('hello wolrd')
res.write('good life')
- res.end():此方法向服务器发出信号,表明已发送所有响应头和主体,该服务器应该视为此消息已完成。
注意:必须在每个响应上调用此 response.end() 方法,不然浏览器会一直转圈圈等待服务器的相应
res.end()
- 设置http响应状态码
res.statusCode:响应状态码
res.statusMessage:响应状态码对应的消息
response.statusCode = 404;
response.statusMessage = 'Not found';
1XX:Infomational(信息性状态码)接收的请求正在处理
2XX:Success(成功状态码)请求正常处理完毕
3XX:Redirection(重定向状态码)需要进行附加操作以完成请求
4XX:Client Error(客户端错误状态码)服务器无法处理请求
5XX:Server Error(服务器错误状态码)服务器处理请求出错
4.获取客户端get方式提交的参数
客户端通过get方式向服务器提交数据时,所以的数据都以字符串的形式拼接在url中。
这些数据分为2种,路径和参数,例如:
www.xxx.com/2019/10/12?name=zs&gender=man
按上面提交的url为例,/2019/10/12就是访问的路径,"?" 后面的 name=zs&gender=man 就是提交的参数。
这种提交参数的方式被称为 query 传参。
想要获取参数,就要对url进行分割,截取"?" 后面的字符串。然后再进行后面的逻辑处理,最终才能获取对应的key和val。这种方式显然很不方便,node.js已为其封装了一个模块,专门处理这类业务。
这个模块就是 url模块,url模块能处理的不仅仅是query参数,他对用户提交的href做了一系列封装处理:
语法:url.parse()
参数一:要解析的href,例如"http://www.xxx.com/2019/10/12?name=zs&gender=man"
参数二:可选。默认query参数是一个字符串。设置成true,可以将query参数解析成对象。
返回值:url.parse()返回一个对象ulr进行解析封装后的对象,其中pathname属性就是访问路径,query就是包含所有query参数的字符串或对象
const url = require('url')
var result = url.parse("http://www.xxx.com/2019/10/12?name=zs&gender=man")
console.log(result)
运行后控制台输出
{
"protocol": "http:",
"slashes": true,
"auth": null,
"host": "www.xxx.com",
"port": null,
"hostname": "www.xxx.com",
"hash": null,
"search": "?name=zs&gender=man",
"query": "name=zs&gender=man", //参数
"pathname": "/2019/10/12", //路径
"path": "/2019/10/12?name=zs&gender=man",
"href": "http://www.xxx.com/2019/10/12?name=zs&gender=man"
}
url.parse()第二个设置成 true
"query": {
"name": "zs",
"gender": "man"
},
完整的姿势:
//引入http模块
const http = require('http')
//引入url模块
const url = require('url')
//创建服务对象
let server = http.createServer((req,res) =>{
//设置头部信息
res.setHeader("Content-Type","text/html;charset=utf-8")
//获取提交的参数并返回给客户端
res.write(`<h3>访问路径:${url.parse(req.url,true).pathname}</h3>`)
res.write(`<h3>name:${url.parse(req.url,true).query.name}</h3>`)
res.write(`<h3>gender:${url.parse(req.url,true).query.gender}</h3>`)
//结束此次响应
res.end()
})
//开启服务
server.listen(80,"127.0.0.1",function(){
console.log("Server running at http://127.0.0.1:80/")
})
5.获取post方式提交的数据
- 当post方法提交的数据比较大时,会分成多次来提交,每次提交一部分,每次提交都会触发req对象的data事件
- 当所有的数据都被提交完毕时会触发req对象的end事件,可以使用querystring模块的parse()方法来把数据转化对象格式,使用前记得引入这个模块。
- 这种方法只适用于上传非文件数据
<body style="padding:30px;">
<form action="http://127.0.0.1:8001/postMsg" method="POST">
<fieldset>
<legend>上传信息</legend>
<div>
<input type="text" name="title">
</div>
<br>
<input type="submit" value="提交">
</fieldset>
</form>
</body>
const querystring = require('querystring');
// 定义一个用来保存post提交的数据的变量
var allData = ""
//监听data事件
req.on("data",function(chunk){
allData += chunk
})
//监听end事件
req.once('end',function(){
//转换为对象
var dataPost = querystring.parse(allData)
console.log(dataPost.title) //测试1234
})
6.接收上传的文件
使用formidable来处理上传的数据
//引入http模块
const http = require('http')
//引入url模块
const url = require('url')
//引入中间件
var formidable = require('formidable')
//创建服务
let server = http.createServer((req,res) =>{
if(req.method.toLowerCase() === 'post' && req.url === '/file_upload'){
//创建实例
var form = new formidable.IncomingForm();
//设置上传文件存放的目录
form.uploadDir = "./uploads"
//保持原来的文件的扩展名
form.keepExtensions = true;
//解析表单(异步)
form.parse(req, function(err, fields, files) {
//打印普通参数
console.log(fields)
//打印当前文件的路径名
console.log(files.fileUpload.path)
//设置头部信息
res.setHeader("Content-Type","text/html;charset=utf-8")
//响应数据
res.end("表单处理完成")
});
}
})
//开启服务
server.listen(8001,"127.0.0.1",function(){
console.log("Server running at http://127.0.0.1:8001/")
})
控制台打印: