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/")
})


控制台打印:

posted @ 2019-10-12 13:26  ---空白---  阅读(368)  评论(0编辑  收藏  举报