内置模块-Http开启web服务器

201 阅读10分钟

内置模块-Http开启web服务器

服务器相关概念

服务器与客户端

服务器

提供网络服务的一台机器,通过在自己的电脑上安装特殊的软件(或者是运行某段特殊的代码)来提供服务

简单来说:服务器 = 电脑 + 能给其它电脑提供服务的软件

客户端与服务器

提供服务的是服务器,享受服务的是客户端

服务器的类型

根据服务不同,服务器的类型也不同,也就是提供服务的软件也不同

web服务器(重点学习)

安装apache/tomcat/iis或者在nodejs环境写代码来提供:图片/视频/音频浏览/新闻数据浏览等服务的服务器

FTP服务器

安装serv-U软件,为其它电脑提供文件下载,共享服务

数据库服务器

安装mysql软件,为其它电脑提供数据库服务

web服务器

用户通过浏览器来享受web服务器提供的图片,视频,音频等网页内容浏览的服务

用户用url地址来访问某个web服务器上的资源

浏览器端发起请求,web服务器收到请求后,响应这个请求,并将处理结果返回给浏览器

浏览器端与web服务器是通过http(或者是https)协议来进行请求和响应的

1652086363488.png

IP地址

全称:Internet Protocol Address

作用:标识一个网络设备(计算机、手机、电视)在某一个具体的网络当中的地址,要访问某个电脑上的资源,先要找到它的ip

在同一个网络中,计算机的IP是不允许相同的,都是唯一的

IP分类:IPV4(互联网协议第4版)、 IPV6(互联网协议第6版)

IPV4格式:[0-255].[0-255].[0-255].[0-255] 即为四个 0-255 的数字组成

例如:127.0.0.1(本机访问) 或 192.168.106.2(局域网访问) 或 220.181.38.149(外网访问)

IPV6格式:X:X:X:X:X:X:X:X,每个X 以十六进制表示(了解)

例如:FF01:0:0:0:0:0:0:1101 → FF01::1101,可以把连续的一段0压缩为“::”

域名

域名:ip地址的别名

由于ip地址不好记忆,我所以给它们取个好记的别名

127.0.0.1 的别名为 localhost

系统自动解析的,不需要做额外的配置

220.181.38.149的别名为 www.baidu.com

需要域名解析系统把域名翻译成IP地址,需要额外购买和配置

端口

理解:如果理解IP地址(一台服务器)是一栋大商场,端口就是商场中的商铺的编号

一个网络设备可以有65536个端口,范围是从[0,65535])

不同的端口被不同的软件占用,以提供不同的服务

服务器要提供服务必须要通过指定的端口

客户端与服务器都需要通过特定端口要进行通信(http://157.122.54.189:9092) 端口是可以编程分配

有一些端口号是被预定了的

  • http: 80
  • https:443
  • mysql:3306

1652086643662.png

HTTP协议

协议:制定客户端与服务器之间的通讯规则,不同的协议的作用也不同,我们主要了解HTTP协议 http协议

定义:HTTP(HyperText Transfer Protocol) 超文本传输协议,浏览器与web服务器都要遵守的协议 HTTP 协议中明确规定了请求数据和响应数据的格式(报文)

浏览器 请求 资源 要遵守 http 协议: 请求报文(请求行,请求头,请求体)

服务器 返回 资源 要遵守 http 协议: 响应报文(响应行,响应头,响应体)

1652087653972.png

实现一个Web服务器

用http 模块写一个简单的web服务器

HTTP在线文档 nodejs.org/dist/latest…

引入http核心模块

使用createServer来创建服务

使用listen来启动服务,端口为8001(端口可以修改 0 - 65535)

在浏览器输入http://127.0.0.1:8001回车即可看到服务器响应回来的信息:OK

也可以通过ipconfig查看你的本机ip,通过 http://局域网ip:8001回车访问

// 创建第一个web服务器
// 1、导入http模块
const http = require('http')

// 重点注意两个参数
// req request  请求(对象)
// res response  响应(对象)
// 2、创建一个服务(类似后端的事件)
const server = http.createServer((req, res) => {
    // req.method 获取用户请求方式
    //  req.url 获取用户请求地址
    console.log('接受到了客户的请求', req.method, req.url);
    res.end('OKlin')
})
// 3、 监听8001端口并启动web服务器等待客户端请求
server.listen(8002, () => {
    console.log('服务器启动成功提示');
})

1652091149933.png

根据不同的url响应不同的内容

const http = require('http')
const server = http.createServer((req, res) => {
    console.log('接受到了客户的请求', req.method, req.url);
    if (req.url === '/') {
        res.end('Hello Index')  // http://127.0.0.1:8001
    } else if (req.url === '/joke') {
        // 服务器告诉浏览器,响应的内容类型为: 文本,编码格式为 utf8
        res.setHeader('content-type', 'text/html;charset=utf8')
        res.end('哈哈哈~')  //  http://127.0.0.1:8001/joke
    } else {
        // 📤res 响应对象
        res.end('404')
    }
    // 🚨 多个 res.end 被调用会导致服务器崩溃
    // res.end('404')
})
// 3. 开启监听
server.listen(8001, () => {
    console.log('服务器启动成功提示')
})

工作原理

使用http模块在本机上创建一个Web服务器,它来接收浏览器的请求,并给出响应。

1652149524483.png

Http模块创建Web服务器代码解析

引入核心模块require('http'),得到的http是一个对象

http.createServer方法创建一个http服务

createServer方法参数是一个回调函数:当有http请求进来时,它会自动被调用,请求一次,它就被调用一次

req参数:客户端的请求相关数据

res参数:设置对本次请求的响应相关数据

server.listen() 用来监听端口

如果监听成功,则回调函数会执行一次。

如果不成功(例如端口被占用),会报错。

req.url

通过 req.url来获取当前请求的url路径

1652149902850.png

req.url在哪儿?

1652149920383.png

req.url具体用法和效果

代码

1652150008548.png

不同的请求url通过req.url获取的结果

1652150028240.png

res.end()设置响应体

语法:res.end(响应的数据)

end()只能传入buffer或者是String类型的数据

作用:设置响应体并结束本次请求

用法:在createServer的回调函数中使用

1652151275753.png

注意:一次请求只能有一个res.end()响应,多个以第一个响应的数据为准,同时服务器报错终止

res.setHeader()设置响应头解决中文乱码

作用:设置响应头信息,控制浏览器的一些行为

语法:res.setHeader(响应头,响应值),两个参数的具体值都是http协议规定的

用法:在createServer的回调函数中使用

注意:

res.setHeader()在res.end()之前才有效

res.setHeader()可以设置多次

应用举例:解决响应中文字符在浏览器显示成乱码问题

 res.setHeader(“Content-Type”,”text/html;charset=utf8”):

1652151338772.png

res.statusCode设置状态码

场景:浏览器输入了一个不存在的url,则服务器返回404状态码

语法:res.statusCode = 状态码,状态码是http协议规定的

状态码:   500 (服务器异常)    404(资源找不到)

注意:res.statusCode只有在res.end()前执行才有效

1652151377891.png

content-type作用

在http协议中,content-type用来告诉对方本次传输的数据的类型是什么

在请求头中设置content-type来告诉服务器,本次请求携带的数据是什么类型的

在响应头中设置content-type来告诉浏览器,本次返回的数据是什么类型的

res.setHeader方法可以设置content-type这个响应头,浏览器根据不同类型做出不同解析

请求头响应头都可以设置content-type

常见的几种文件类型及content-type

常见的几种文件类型及content-type

  • .html:res.setHeader('content-type', 'text/html;charset=utf8')
  • .css:res.setHeader('content-type', 'text/css;charset=utf8')
  • .js:res.setHeader('content-type', 'application/javascript')
  • .png:res.setHeader('content-type', 'image/png')
  • json数据:res.setHeader('content-type', 'application/json;charset=utf-8')

※ 如果读取.html的文件内容,但是content-type设置为了text/css则浏览器将不会当作是html页面来渲染了

练习案例 随机笑话

const http = require('http')
const server = http.createServer((req, res) => {
    console.log('接受到了客户的请求', req.method, req.url);
    if (req.url === '/joke') {
        const arr = ['1、在我还在上大学那会,有一天去系办找辅导员,正好在楼梯遇到一个平日很装的同学,我上楼同学下楼,相遇的刹那,同学一仰头,很是高傲的瞄了我一眼,嘴角划过一丝不屑的笑,保持这种姿态直接一步跨出,然后我羞羞的伸出了脚,然后整栋楼传来嗷的一声……', '2、一男子应聘,面试官问在上一个公司离职的原因,男子答:公司搬了新大楼,没有告诉我地址', '3、 本人20多岁妹纸一枚,从小特别怕痒一次去一个老中医那推拿,单独房间他是五六十岁大叔级别我往床上一趴,他推一下我嗷一嗓子,推一下我嗷一嗓子半分钟后他忍不住了说,不收你钱了你走吧,我是一个要名誉的人……', '4、 元旦去看电影。看得好好的,突然屏幕黑了,上来一个主持人,拿着话筒,说:“下面哪个大哥带别人媳妇来的?赶紧跑吧,人家老公来抓了!”然后我一回头,就没有几个人了……', '5、宫廷玉液酒,一百八一杯,这酒怎么样啊?听我给你吹。一杯你开胃,(我喊了一声美)二杯你肾不亏,(哈哈 还是美),三杯五杯进了肚,保证你的小脸啊,是白里透着红啊,红里透着黑', '6、夜空一颗流星划过,我连忙许了心愿,希望你能变漂亮些,谁知刚许完心愿,流星“嗖”地返回来,对我说:大哥!诚心为难我是不是?!', '7、一天阿呆突然发现他有大姨,二姨,四姨,却没有三姨。于是就去问他爸:为什么我没有三姨?难道三姨在小的时候就死了?他爸怒道:你三姨就是你妈!', '8、某人养一猪,烦,弃之,然猪知归路,数弃无功。一日,其驾车转了很多弯弃猪,深夜致电家人,问:“猪归否?”答曰:“已归!”其怒吼:“让它接电话,老子迷路了!"', '9、看哪个银行缩写最牛:中国建设CBC(存不存),中国银行BC(不存),中国农业银行ABC(啊不存),中国工商银行ICBC(爱存不存),民生银行CMSB(存吗傻B)。', '10、艺术家问画廊老板是否有人买他的画。老板:“有个人问我你死后这些画会增值多少,我告诉他后他买了一幅画。不过他说他是你的医生。”', '11、胡萝卜见客户,恭敬地递上名片,客户看名片问:你怎么叫高丽参啦?胡萝卜小腰一挺,“人家哈韩了嘛!”']
        const index = Math.round(Math.random() * arr.length-1)
        // 解析字符编码 中文乱码
        res.setHeader('content-type', 'text/html;charset=utf8')
        res.end(`${arr[index]}`)
    }  else {
        // 📤res 响应对象
        res.end('404')
    }
})
// 3. 开启监听
server.listen(8001, () => {
    console.log('服务器启动成功提示')
})

Web服务器处理接口响应

接口请求方式

发送接口请求的类型

  • get:在地址栏中直接访问这个url就是get方式。
  • post:通过表单提交,可以设置$.ajax的type为post
  • delete
  • put web服务器通过req.method获取当前请求的类型

1652158961488.png

接口的各种表现形式

  1. get请求不带参数的接口: http://127.0.0.1:8003/getHero
  2. get请求带参数的接口: http://127.0.0.1:8003/getHero?heroName=后羿
  3. post请求接口 http://127.0.0.1:8003/addHero (参数在请求报文体中传输)

使用软件测试接口请求方式

const http = require('http')

// 创建服务
const server = http.createServer((req, res) => {
    // 解构 请求方式 method 和请求地址 url
    const { method, url} = req
    // 防止中文乱码
    res.setHeader('Content-Type','text/html;charset=utf8')
    // 通过分支,区别不同的客户端请求 响应不同结果
    if(method === 'GET' && url === '/meber/car') {
        // 如果是 get /meber/car
        res.end('获取购物车列表')
    }else if (method === 'POST' && url === '/meber/car' ){
         // 如果是 POST /meber/car
        res.end('加入购物车(新增)')
    }else if (method === 'DELETE' && url === '/meber/car' ){
        // 如果是 DELETE /meber/car
        res.end('删除购物车商品')
    }else {
        // 以上都不是 兜底响应404 因为服务器没响应 浏览器会一直转圈圈等待
        res.statusCode = 404
        res.end('404')
    }
    
    res.statusCode = 404
})
// 启动服务(监听)
server.listen(8000, () => {
    console.log('服务器启动成功');
})