1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > node.js的http模块

node.js的http模块

时间:2021-09-14 05:45:39

相关推荐

node.js的http模块

http模块

http协议:超文本传输协议(互联网应用最广泛的协议之一)

http请求方法:

get获取数据

post新增数据

put/patch更新数据

delete删除数据

head/options/connect/trace

URL统一资源定位符,其本身也是一个字符串。

客户端与服务

在网络节点中,负责消费资源的电脑,叫做客户端。

负责对外提供网络资源的电脑,叫做服务器。

http模块是node.js官方提供的、用来创建web服务器的模块。通过http模块提供的http.createServer()方法,就能方便的把一台普通电脑变成一台web服务器,从而对外提供web资源服务。

使用http模块创建web服务器,需要先导入

const http=require('http')

服务器和普通电脑的区别就是服务器上安装了web服务器软件,例如IIS,Apache等,在Node.js中不需要使用第三方web服务器软件,可以基于Node.js提供的http模块,简单代码手写一个服务器软件,对外提供web服务。

服务器相关概念

ip地址

ip地址是互联网上每台计算机的唯一地址,ip地址具有唯一性。

ip地址的格式通常是“点分十进制”,表示成(a,b,c,d)的形式,其中a,b,c,d都是0~255之间的十进制整数。eg:(192.168.1.1)

互联网中的每台web服务器都有自己的ip的地址,可以在Windows终端运行ping 命令,即可查看百度服务器的ip地址。

域名和域名服务器

ip地址不直观不便于记忆,于是有字符型的地址方案-域名地址

ip地址和域名是一一对应的关系,这种对应关系放在一种叫做域名服务器的电脑中。使用者只需要通过域名访问对应服务器即可,对应的转换工作由域名服务器实现。

因此,域名服务器就是提供ip地址和域名之间的转换服务的服务器。

注意:开发测试期间,127.0.0.1对应的域名是localhost,他们都代表我们自己的这台电脑,在使用效果上没有任何区别。

端口号

一台电脑可以运行成百上千个web服务,每个web服务都对应一个唯一的端口号,客户端发送过来的网络请求,通过端口号,可以被准确的交给对应的web服务进行处理。

注意:

每个端口号不能同时被多个web服务占用。

在实际应用中,url中的80端口可以被省略。

localhost:80可以直接访问localhost

网页中URL的使用

URL可以分为相对路径和绝对路径

相对路径:相对于当前文件位置的路径

绝对路径:目标文件在硬盘上的真实路径(最精确路径)

html中link引入文件的最好的一种方式应该是绝对路径

<link rel="stylesheet" href="/index.css">

绝对路径

绝对路径靠谱性强,相对容易理解在项目中运用比较多

/web直接向目标资源发送请求,容易理解。网站的外链会用此形式

///web与页面URL的协议拼接行测好难过完整的URL再发送请求。大型网站使用较多。

/web与页面的协议主机名,端口拼接形成完整的URL再发送请求。中小型网站。

相对路径

比如/about/h5.html

相对路径是在发送请求时,与当前页面URL路径进行计算,得到完整的URL后,再发送请求,学习阶段用的较多。

网页中URL使用场景总结

包括但不限于以下场景

a标签hreflink标签hrefscript标签hrefimg标签srcvideo audio标签的srcform中的actionAJAX请求中的URL

浏览器查看HTTP报文

可以使用一个表单提交的demo做相关测试

<form action="http://127.0.0.1:9000" method="post"><input type="text" name="username"><input type="text" name="password"><input type="submit" value="提交"></form>

在浏览器打开对应的html文件(注意在此之前运行http服务端,监听端口开启服务),输入表单信息提交,在F12控制台可以查看网络

获取请求行和请求头

想要获取请求的数据,需要通过request对象

request.method请求方法

request.httpVersion请求版本request.url请求路径require(‘url’).parse(request.url).pathname URL路径require(‘url’).parse(request.url,true).query url查询字符串request.headers请求头request.on(‘data’,function(chunk){});request.on(‘end’,function(){});

注意事项

request.url只能获取路径以及查询字符串,无法获取URL中的域名以及协议的内容request.headers将请求信息转化为一个对象,并将属性名都转化成了小写。关于路径:如果访问网站的时候,只填写可ip地址或者域名信息,此时的请求路径是/favicon.ico:浏览器自动发送的请求

创建最基本的web服务器

基本步骤

导入http模块

const http=require('http')

创建web服务器实例

调用http.createServer()方法快速创建一个web服务器实例

const server=http.createServer()

为服务器实例绑定request事件,监听客户端请求

// 使用服务器实例的.on()方法,为服务器绑定一个request事件server.on('request', (req, res) => {// 只要有客户端来请求我们自己的服务器,就会触发request事件,从而调用这个事件处理函数console.log('Hello HTTP Server')})

req是一个对请求报文的封装对象,可以获取请求报文的相关内容

res是一个对响应报文的封装对象,可以获取响应报文的相关内容

启动服务器

调用服务器的.listen()方法,即可启动当前的web服务器实例

// 调用服务器实例的.listen(端口号,cb回调)方法,即可启动当前的web服务器实例server.listen(9000, () => {console.log('服务已经启动')})

可以在powdershell执行node命令,

vscode的终端新建终端也可以执行node命令,ctrl+c暂停服务器

注意事项

命令行ctrl+c停止服务当服务启动后,更新代码必须重启服务才能生效响应内容中文乱码的解决办法

response.setHeader('Content-type', 'text/html;charset=utf-8');

端口号被占用

Error: listen EADDRINUSE: address already in use :::9000

(1)关闭当前正在运行监听端口的服务

(2)修改其他端口号

HTTP协议默认端口是80,HTTP服务开发常用端口有3000,8080,8090,9000等

如果端口被其他程序占用,可以使用资源监视器找到占用端口的程序,然后使用任务管理器关闭对应的程序。

桌面底部任务栏右键任务管理器,点击性能,窗口底部就有资源监视器

根据资源监视器找到占用端口的进程的pid,在资源管理器根据pid找到进程右键结束任务,端口就可以用了。另外如果pid没有显示pid,在名称那里右键选择pid就显示了如图

HTTPS协议默认端口是443

req请求对象

只要服务器接收到了客户端的请求,就会调用通过server.on()为服务器绑定的request事件处理函数。

如果想在事件处理函数中,访问与客户端相关的数据或属性,可以使用如下方法:

server.on('request', (req) => {//req是请求对象,它包含了与客户端相关的数据和属性,例如:// req.url是客户端请求的URL地址// req.method是客户端的method请求类型const str = 'Your request url is ${req.url}, and request method is ${req.method}'console.log(str)})

运行的完整的代码如下

const http = require('http')const server = http.createServer()server.on('request', (req) => {//req是请求对象,它包含了与客户端相关的数据和属性,例如:// req.url是客户端请求的URL地址// req.method是客户端的method请求类型const str = 'Your request url is ${req.url}, and request method is ${req.method}'console.log(str)})// 调用服务器实例的.listen(端口号,cb回调)方法,即可启动当前的web服务器实例server.listen(1314, () => {console.log('http server running at http://127.0.0.1')})

运行80端口报错

所以换成了1314端口

运行成功

res响应对象

在服务器的request事件处理函数中,如果想访问与服务器相关的数据或属性,可以使用如下方式:

server.on('request', (req, res) => {// res是响应对象,它包含了与服务器相关的数据和属性,例如 要发送到客户端的字符串const str = 'Your request url is ${req.url}, and request method is ${req.method}'// res.end()方法向客户端发送指定内容,并结束这次请求的处理过程res.end(str)})

完整运行的代码

// 导入http模块const http = require('http')// 创建web服务器实例const server = http.createServer()// req是请求对象,包含与客户端相关的数据和属性server.on('request', (req,res) => {// req.url事故客户端请求的url地址const url = req.url// req.method是客户端请求的method类型const method = req.methodconst str = 'Your request url is ${url}, and request method is ${method}'console.log(str)// 调用res.end()方法,向客户端响应一些内容res.end(str)})server.listen(1314, () => {console.log('server running at http://127.0.0.1')})

运行结果截图

创建HTTP报文和提取请求体的代码示例

const http = require('http');// 创建服务对象const server = http.createServer((request, response) => {// 获取请求的方法console.log(request.method);// 获取请求的urlconsole.log(request.url);//只包含url中的路径与查询字符串// 获取HTTP协议的版本号console.log(request.httpVersion)// 获取HTTP的请求头console.log(request.headers.host);response.end('http');//设置响应体});// 监听端口,启动服务server.listen(9000, () => {console.log('服务已经启动')});

在地址栏输入请求

request.url会在终端输出url路径与查询字符串

提取HTTP报文的请求体

const http = require('http');// 创建服务对象const server = http.createServer((request, response) => {// 声明一个变量let body = '';// 绑定data事件request.on('data', chunk => {body += chunk;})// 绑定end事件request.on('end', () => {console.log(body);// 响应response.end('Hello HTTP');});});// 监听端口,启动服务server.listen(9000, () => {console.log('服务已经启动')});

在地址栏直接发送请求是get请求,请求体为空,服务端返回空

可以借助html的表单发送不为空的请求

提取HTTP报文中URL的路径与查询字符串

const http = require('http');const url = require('url');const server = http.createServer((request, response) => {let res = url.parse(request.url, true);console.log(res);let pathname = res.pathname;let keyword = res.query.keyword;console.log(keyword);response.end('url');});// 监听端口,启动服务server.listen(9000, () => {console.log('服务已经启动')});

一开始没有监听端口启动服务,我还想怎么node命令之后没有任何反应呢,搞笑。。。

还有一种方式,代码如下

const http = require('http');const { URL } = require('url');const server = http.createServer((request, response) => {// 实例化url的对象// let url = new URL('/search?a=100&b=200');// let url = new URL('./search?a=100&b=200', 'http://127.0.0.1:9000');let url = new URL(request.url, 'http://127.0.0.1:9000');// 输出路径console.log(url.pathname);// 输出keycode查询字符串console.log(url.searchParams.get('keyword'));response.end('url new');});server.listen(9000, () => {console.log('服务已经启动')});

注意实例化url对象的代码。

HTTP请求练习题

按照以下要求搭建HTTP服务

请求类型get,请求地址为/login和/reg响应体结果分别是登录页面和注册页面。

核心步骤

获取请求的url地址设置默认的相应内容为404 Not found判断用户请求的是否为/login.html判断用户请求的是是否是/reg.html设置Content-Type响应头,防止中文乱码使用res.end()把内容响应给客户端

基础的代码模板如下

// 1.导入http模块const http = require('http');// 2.创建服务对象const server = http.createServer((request, Response) => {Response.end('practise');});// 3.监听端口,启动服务server.listen(9000, () => {console.log('服务已经启动,,端口9000监听中')})

上述代码为基础的代码模板,因为有请求就会执行回调函数,所以功能函数会放在回调函数当中,并且需要在当中判断请求方法以及是否url路径是否与要求匹配。

由于最后只能有一个end方法,所以在写完判断的end的方法之后要把原来的practise的end方法删除掉。否则会出现write after end 的报错信息。

删除后运行页面的内容出现中文乱码,这个时候只需要设置response.setHeader即可。

let method=request.method;

可以简写为

let { method } = request;

request里面有method属性,所以可以用赋值的方式去获取。[对象解构]

完整代码如下,最后的else保证了谷歌浏览器favicon.ico的响应

// 1.导入http模块const http = require('http');// 2.创建服务对象const server = http.createServer((request, Response) => {// 获取请求的方法let { method } = request;// 获取请求的url路径let { pathname } = request;// let pathname = new URL(request.url, 'http://127.0.0.1');Response.setHeader('content-type', 'text/html;charset=utf-8');// console.log(pathname);// console.log(method);// 判断if (method === 'GET' && require('url').parse(request.url).pathname === '/login') {// 登录的情形Response.end('登录页面');} else if (method === 'GET' && require('url').parse(request.url).pathname === '/reg') {Response.end('注册页面');} else {Response.end('404 Not Found');}});// 3.监听端口,启动服务server.listen(9000, () => {console.log('服务已经启动,,端口9000监听中')})

【bug记录】

判断的逻辑如下,判断之前打印pathname和method,前者是url集合后者是get,login和reg页面也无法正常切换,页面无论如何只显示404notfound的默认样式。

最后将pathname换成了require(‘url’).parse(request.url).pathname,页面切换正常。或者在上面使用对象解构声明let { pathname } = request;

//存在问题的代码示例if (method === 'GET' && pathname === '/login') {// 登录的情形Response.end('登录页面');} else if (method === 'GET' && pathname === '/reg') {Response.end('注册页面');} else {Response.end('404 Not Found');}

设置HTTP响应报文

设置响应状态码 response.statusCode

设置响应状态描述 response.statusMessage(用的非常少)

设置响应头信息 response.setHeader(‘头名’,‘头值’)

设置响应体 response.write(‘xx’)或者 response.end(‘xxx’)

在服务对象里设置响应状态码

Response.statusCode = 203;

默认的响应状态码是200,多次设置后面设置的会覆盖前面的哈哈哈。

在服务对象里面设置响应状态描述

Response.statusMessage = ‘sorry tony’;

在服务对象里面设置响应头

Response.setHeader(‘content-type’, ‘text/html;charset=utf-8’);Response.setHeader(‘server’, ‘node.js’);// Response.setHeader(‘暗号’, ‘是谁在等天明’);//errorResponse.setHeader(‘test’, [‘a’, ‘b’, ‘c’]);

响应头设置中文内容给会报错

响应体的设置

Response.write(‘love’);Response.write(‘love’);Response.write(‘love’);Response.write(‘love’);Response.end();//设置响应体

响应体可以重复设置,最后会叠加呈现在页面上,一般write设置了载体,end里面就不会设置载体了。

HTTP响应练习题

搭建HTTP服务,响应一个4列3行的表格,并且要求表格有隔行换色效果,且点击单元格能高亮显示

const http = require('http');const fs = require('fs');const server = http.createServer((request, Response) => {// 读取文件内容let html = fs.readFileSync(__dirname + '/http响应表格.html');Response.end(html);//end可以是字符串可以是buffer});server.listen(9000, () => {console.log('服务已经启动,,端口9000监听中')})

html部分如下

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title></head><style>td {padding: 20px 40px;}table tr:nth-child(odd) {background: #aef;}table tr:nth-child(even) {background: #fcb;}table,td {border-collapse: collapse;}</style><script>// 获取所有的tdlet tds = document.querySelectorAll('td');// 遍历tds.forEach(item => {item.onclick = function () {this.style.background = '#red';}})</script><body><table border="1"><tr><td></td><td></td><td></td><td></td></tr><tr><td></td><td></td><td></td><td></td></tr><tr><td></td><td></td><td></td><td></td></tr></table></body></html>

前几次运行出现的问题是js部分代码执行的功能是点击对应的表格出现光标,而不是高亮显示,暂时不知道问题出在哪里。

第二天,我笑了,script标签里面的代码写进window.οnlοad=function(){}里面就好了呀哈哈哈。

网页资源加载基本过程

html

<head><link rel="stylesheet" href="./index.css"></head><body><h1>测试</h1><hr><img src="./素材/msld1.jpg"><script src="./index.js"></script></body>

css

body{height: 100vh;padding: 20px;box-sizing: border-box;background: linear-gradient(right bottom,#aef,#c90);}hr{margin: 20px 0;border-bottom: solid 1px rgba(0, 0, 0, 0.363);}

js

window.onload = function () {let img = document.querySelector('img');img.onclick = function () {alert('点我干嘛')}}

【记录bug】

考虑添加else条件判断返回img

,依旧不可以

移动图片资源到英文文件夹,依然不显示。

最后文件正常显示是在vscode的html文件中右键 open with live server,在端口5500下正常显示。

静态资源服务

静态资源是指内容长时间不发生改变的资源,比如图片视频,脚本文件,字体文件,html文件等等

动态资源是内容经常更新的资源你,比如百度首页,网易首页,京东搜索列表页面等等。

const http = require('http');const fs = require('fs');// 创建服务对象const server = http.createServer((req, res) => {// 获取请求url的路径let { pathname } = new URL(req.url, 'http://127.0.0.1');// 拼接文件路径let filePath = __dirname + '/page' + pathname;// 读取文件fs异步APIfs.readFile(filePath, (err, data) => {if (err) {Response.statusCode = 500;Response.end('文件读取失败');return;//防止代码继续往后执行}// 响应文件内容Response.end(data);//设置响应体})});server.listen(9000, () => {console.log('服务已经启动')});

静态资源目录与网站根目录

http服务在哪个文件夹中寻找静态资源,那个文件夹就是静态资源目录,也称之为网站根目录

vscode中使用live-server访问HTML时,它启动的服务网站根目录是谁

vscode 当前打开的文件夹

const http = require('http');const fs = require('fs');// 创建服务对象const server = http.createServer((req, res) => {// 获取请求url的路径let { pathname } = new URL(req.url, 'http://127.0.0.1');// 声明一个变量let root = __dirname + '/../';// 拼接文件路径let filePath = root + pathname;// 读取文件fs异步APIfs.readFile(filePath, (err, data) => {if (err) {res.setHeader('content-type', 'text/html;charset=utf-8');res.statusCode = 500;res.end('文件读取失败');return;//防止代码继续往后执行}// 响应文件内容Response.end(data);//设置响应体})});server.listen(9000, () => {console.log('服务已经启动')});

运行结果

设置资源类型mime

媒体类型(MIME类型)是一种标准,用来表示文档、文件或者字节流的性质和格式。

HTTP服务可以设置响应头Content-Type来表明响应体的MIME类型,浏览器会根据该类型决定如何处理资源。

常见文件对应的mime类型

application/octet-stream

这是应用程序文件的默认值。未知的应用程序文件,浏览器一般不会自动执行或询问执行。text/plain

文本文件默认值。即使它意味着未知的文本文件,但浏览器认为是可以直接展示的。

text/css

text/html

text/javascript

对于未知的资源类型,可以选择application/octet-stream类型,浏览器在遇到该类型的响应时,会对响应体内容进行独立存储,也就是我们常见的下载效果。

const http = require('http');const fs = require('fs');const path = require('path');// 创建服务对象const server = http.createServer((req, res) => {// 获取请求url的路径let { pathname } = new URL(req.url, 'http://127.0.0.1');// 声明一个变量// let root = __dirname + '/../';let root=__dirname// 拼接文件路径let filePath = root + pathname;// 读取文件fs异步APIfs.readFile(filePath, (err, data) => {if (err) {res.setHeader('content-type', 'text/html;charset=utf-8');res.statusCode = 500;res.end('文件读取失败');return;//防止代码继续往后执行}// 获取文件的后缀名let ext = path.extname(filePath);console.log(ext);res.setHeader('content-type','xxx')// 响应文件内容res.end(data);//设置响应体})});server.listen(9000, () => {console.log('服务已经启动')});

运行结果截图

// 声明一个变量let mimes = {html: 'text/html',css: 'text/css',js: 'text/javascript',png: 'image/png',jpg:'image/jpeg'}let type = mimes[ext];if (type) {// 匹配到res.setHeader('content-type', type);} else {// 没有匹配到res.setHeader('content-type', 'application/octet-stream');}

如果css资源中有中文(中文注释也算),那么访问具体的文件的时候页面也会出现乱码,html的不会乱码因为meta设置字符是utf-8,当然,响应头的charset优先级更高一些

完善错误处理

打开一个不存在的文件报错,完善错误处理

if (err) {// 设置字符集res.setHeader('content-type',' text/html; charset=utf-8');// 判断错误的代号switch (err.code) {case 'ENOENT':res.statusCode = 404;res.end('<h1>404 Not Found </h1>');case 'EPERM':res.statusCode = 403;res.end('<h1>403 Forbidden </h1>');}return;}

第一个err访问一个不存在的文件,第二个err通过手动修改html的读取属性的权限,禁止读取,然后在测试。右键属性安全编辑里面就可以操作。

第三个请求方式的错误处理

可以借助form表单进行post请求,打开表单提交表单发送post请求

第五种其他的错误处理

default:res.statusCode=500;res.end('<h1>500 Internal Server Error </h1>');

GET和POST使用场景

get请求的场景

在地址栏直接输入url访问点击a链接link标签引入cssscript标签引入jsvideo和audio引入多媒体img标签引入图片form标签中的method为get(不区分大小写)ajax中的get请求

post请求的场景

form标签中的method为post(不区分大小写)AJAX中的post请求

get与post请求的区别

get和post是http协议请求的两种方式,主要有以下几个区别

作用,get主要用来获取数据,post主要用来提交数据参数位置。get带参数请求是将参数缀到URL之后,post带参数是将参数放到请求体中。安全性。 post请求相对get安全一些,因为在浏览器中参数会暴露在地址栏中get请求大小有限制,一般为2k,而post请求则没有大小限制。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。