一步一步教你用Node实现完整的http服务端

背景

今天没事看了之前写过的博客,发现搭建HTTP服务器的博客并不细致完整;也无任何路由处理,以及响应处理。秉着对读者和自己负责的态度,决定再写一个更新篇。本文章将以以下目录顺序去介绍:

为了便于新手理解,在开始之前,先来了解一下几个概念(老手可直接跳过)。

概述

1. 网站的组成

网站应用程序主要分为两大部分:客户端服务器端

  • 客户端
    在浏览器中运行的部分,就是用户看到并与之交互的界面程序。使用HTML、CSS、JavaScript构建。
  • 服务器端:
    在服务器中运行的部分,负责存储数据和处理应用逻辑。
    两者的关系如图所示:
    在这里插入图片描述

2. 超文本传输协议

超文本传输协议(英文:HyperText Transfer Protocol,缩写:HTTP)规定了如何从网站服务器传输超文本到本地浏览器,它基于客户端服务器架构工作,是客户端(用户)和服务器端(网站)请求和应答的标准。

报文
在HTTP请求和响应的过程中传递的数据块就叫报文,包括要传送的数据和一些附加信息,并且要遵守规定好的格式。报文的形式如图所示:

在这里插入图片描述

请求方式

  • GET 请求数据
  • POST 发送数据

PS:据我了解还有其他请求方式,感兴趣可自行百度了解。

响应状态码

  • 200 请求成功
  • 404 请求的资源没有被找到
  • 500 服务器端错误
  • 400 客户端请求有语法错误

PS:据我了解还有其他状态码,感兴趣可自行百度了解。

扫描二维码关注公众号,回复: 14489522 查看本文章

响应内容类型

  • text/html 网页
  • text/css css文件
  • application/javascript JS脚本
  • image/jpeg 图片
  • application/json json数据

搭建服务端

这里就不再赘述如何搭建了,直接上代码,如果不清楚可以看我之前写的如何用Node搭建一个完整http服务器

//引入http模块
const http = require('http')

//创建HTTP服务器
let app = http.createServer();

//绑定监听事件
//回调函数中req代表请求,res代表响应
app.on("request", (req, res) => {
    
    

});
//设置服务器端口
app.listen(2020,function(){
    
    
	console.log('服务器已经开启,端口是2020')
})

此时建立开启的服务是没有任何任何响应的,我们可以在回调函数中直接加入响应内容,但是实际工作中是要根据用户的请求来响应内容的。那么如何来将用户的请求分类呢,这里我们就需要路由处理了。

路由处理

这里我们设计的思路是:

  1. 将所有的按请求方式分类
  2. 不同类别单独处理
  3. 获取请求的关键信息作为路由依据

首先将路由分类:
PS:这里只修改app事件中的代码,其余代码无改动,如改动会提示说明。必要文字叙述以注释的形式展开了,

//回调函数中req代表请求,res代表响应
app.on("request", (req, res) => {
    
    
    //首先使用method获取求情方式
    let method = req.method;
    console.log(method)
});

运行服务端,在浏览器输入以下地址:

http://localhost:2020/

可以看到输出了请求方式:
在这里插入图片描述
使用分支语句,根据请求方法将请求分类,代码如下:

app.on("request", (req, res) => {
    
    
    //首先使用method获取求情方式
    let method = req.method;
    // 分类
   if(method=="GET")
     {
    
    

   }
   else if(method=="POST"){
    
    

   }
});

接着需要获取请求的关键信息,在这里我们使用一个Node中内置模块url,它当中提供了一个方法可以格式化请求连接。下面是它的使用:
PS:在代码的开始引入url模块。

const url = require('url')
app.on("request", (req, res) => {
    
    
    //首先使用method获取求情方式
    let method = req.method;
    //格式化请求链接
    let newUrl = url.parse(req.url);
    // 使用对象.的方法获取关键信息pathname
    let pathname = url.parse(req.url).pathname
    // 分类
   if(method=="GET")
     {
    
    
        console.log(newUrl)
        console.log(pathname)
   }
   else if(method=="POST"){
    
    

   }
});

此时浏览器中的请求为:

http://localhost:2020/index?name=alai&age=22

控制台的输出为:
在这里插入图片描述
接着我们假设网页中有三个页面:

  • index.html
  • list.html
  • footer.html

下面我们编写路由结构,代码如下:

app.on("request", (req, res) => {
    
    
    //首先使用method获取求情方式
    let method = req.method;
    //格式化请求链接
    // let newUrl = url.parse(req.url);
    // 使用对象.的方法获取关键信息pathname
    let pathname = url.parse(req.url).pathname
    // 分类
    if (method == "GET") {
    
    
        // console.log(newUrl)
        // console.log(pathname)
        // ||后面的意思是:默认将localhost:2020设为首页
        if (pathname == "/index" || pathname == "/") {
    
    
            console.log("响应首页")
        }
        else if (pathname == "/list") {
    
    
            console.log("响应列表页")
        } else if (pathname == "/footer") {
    
    
            console.log("响应页脚")
        }
    }
    else if (method == "POST") {
    
    

    }
});

此时浏览器的访问链接如下:

http://localhost:2020/list

此时控制台的输出为:
在这里插入图片描述
此时虽然能够对请求进行分类,客户端访问链接以后仍然收不到任何内容。想要客户端收到消息就必须在服务端做出响应。

响应请求

在搭建服务端时,我们知道回调函数中参数res用来做出响应。这里我们介绍两个方法:

  1. res.writeHead()
  2. res.end()

res.writeHead()
它用来设置响应头,用法如下所示:

 res.writeHead(200, {
    
    
                    "content-Type": "text/html;charset=utf8"
                })

其中200表示我们在第一部分提到过的响应状态码,conten-type表示响应内容的类型,charset表示编码类型,一般为utf8。
res.end()
它用来响应内容,用法如下:

  res.end("响应结果")

下面我们来编写简单响应内容,代码如下:

app.on("request", (req, res) => {
    
    
    //首先使用method获取求情方式
    let method = req.method;
    //格式化请求链接
    // let newUrl = url.parse(req.url);
    // 使用对象.的方法获取关键信息pathname
    let pathname = url.parse(req.url).pathname
    // 分类
    if (method == "GET") {
    
    
        // console.log(newUrl)
        // console.log(pathname)
        res.writeHead(200, {
    
    
            "content-Type": "text/html;charset=utf8"
        })
        // ||后面的意思是:默认将localhost:2020设为首页
        if (pathname == "/index" || pathname == "/") {
    
    
            res.end("<h1>欢迎来到首页</h1>")
        }
        else if (pathname == "/list") {
    
    
            res.end("<h1>欢迎来到列表页</h1>")
        } else if (pathname == "/footer") {
    
    
            res.end("<h1>欢迎来到页脚</h1>")
        } else {
    
    
            res.writeHead(404, {
    
    
                "content-Type": "text/html;charset=utf8"
            })
            res.end("<h1>你要找的页面走丢了</h1>")
        }
    }
    else if (method == "POST") {
    
    

    }
});

此时的运行结果如下所示:
列表页:
在这里插入图片描述
首页:
在这里插入图片描述
不存在的页面:
在这里插入图片描述
不存在时的状态码:
在这里插入图片描述
到这里,一个简易的http服务器就搭建好了,但是要用的实际项目中还有很长学习之路要走,还请继续坚持学习。

本博客旨在分享自己的所学和稀少的经验,也希望可以帮助初学者能更好的理解知识。
整理编写不易,看到这里如果对您有一丝丝帮助,还请我一个小小的赞,也可关注我,对我也是一种激励,工作之余尽量多分享内容。
鉴于笔者资历尚浅,如有疏漏不足之处欢迎指出,更欢迎兴趣相投者交流学习。下面是笔者的微信:
在这里插入图片描述

记2020年8月27日
于天津

猜你喜欢

转载自blog.csdn.net/weixin_43482353/article/details/108254628