本文已同步到github, web开发中,必需要了解的HTTP相关知识,欢迎收藏,欢迎star。javascript
本文主要记录与HTTP相关的具体概念和知识,关于HTTP协议的诞生和历史发展,很少作介绍,可是既然是写HTTP,顺带说两句,上下文也能衔接的上。html
CERN(欧洲核子研究组织)的蒂姆 • 伯纳斯 - 李(Tim Berners - Lee)博士提出了一种能让远隔两地的研究者们共享知识的设想,因而HTTP慢慢的诞生了。java
另外,HTTP协议是无状态协议,因而为了保存用户的状态,cookie诞生了。node
HTTP协议是创建在TCP链接之上的,当浏览器输入URL进行访问,浏览器冲URL中解析出主机名和端口,浏览器创建一条与web服务器的链接,而后才进行http请求。git
在客户端与服务端进行http通讯以前,须要创建TCP链接,这时须要三次握手github
(1) 请求新的TCP链接,客户端发送一个小的TCP分组,这个分组设置一个特殊的SYN标记,代表是一个客户端请求。web
(2) 若是服务器接受这个链接,就会对一些链接参数进行计算,并向客户端回送一个TCP分组,发送SY和ACK标记,代表链接请求已经被接受跨域
(3) 最后,客户端向服务器回送一条确认消息,通知服务器链接已经创建。浏览器
创建一个链接须要三次握手,而终止一个链接要通过4次握手。这由TCP的半关闭(half-close)形成的。既然一个TCP链接是全双工(即数据在两个方向上能同时传递),所以每一个方
向必须单独地进行关闭。这原则就是当一方完成它的数据发送任务后就能发送一个FIN来终止
这个方向链接。当一端收到一个FIN,它必须通知应用层另外一端几经终止了那个方向的数据传
送。发送FIN一般是应用层进行关闭的结果。
(1) 客户端发送FIN标记到服务器,代表客户端发起关闭链接缓存
(2) 服务器接收客户端的FIN标记并,向客户端发送FIN的ACK确认标记
(3) 服务器发送FIN到客户端,服务器关闭链接
(4) 服务器端发送一个FIN的ACK确认标记,确认链接关闭
创建持久链接的请求和响应交互:
使用wireshark进行数据抓包:
这里向你们推荐一款抓包软件Wireshark,能够用来分析TCP链接的创建和断开过程,以及抓取HTTP请求和相应的信息等,下面是我进行一次客户端和服务端通讯的抓包数据截图:
HTTP协议报文是应用程序之间发送的数据块,也就是客户端和服务端用于交互的信息。客户端的报文叫作请求报文,服务器端的报文叫作响应报文。
HTTP报文由起始行、首部和实体的主体(也称报文主体或主体)组成。起始行和首部以一个回车符和换行符做为结束,主体部分能够是二进制数据,也能够为空。
请求报文起始行:
请求报文起始行说明了要作什么,由请求方法 、请求URI和协议版本构成。
GET /index.html HTTP/1.1
响应报文起始行:
响应报文的起始行,由协议版本、状态码和缘由短语构成。
HTTP/1.1 200 OK // OK就是缘由短语
首部字段分类
1.通用首部
客户端和服务端均可以使用的首部
通用首部字段表:
2.请求首部
请求报文特有的首部,为服务器提供了一些额外的信息,补充了请求的附加内容、客户端信息、响应内容相关的优先级等信息。
请求首部字段
3.响应首部
响应报文特有的字段
响应首部字段表:
4.实体首部
用于针对请求报文和响应报文主体部分使用的首部
5.扩展首部
扩展首部是非标准的首部,由应用程序开发者建立,但还未添加到已批准的HTTP标准中去。
状态码的职责是当客户端向服务器端发送请求时,描述返回的请求结果。借助状态码,用户能够知道服务器端是正常处理了请求,仍是出现了错误。
状态码分类:
状态码区间 | 类别 |
---|---|
100~199 | 信息性状态码 |
200~299 | 成功状态码 |
300~399 | 重定向状态码 |
400~499 | 客户端错误状态码 |
500~599 | 服务器错误状态码 |
经常使用状态码列表:
状态码 | 缘由短语 | 含义 |
---|---|---|
200 | OK | 表示从客户端发来的请求在服务器端被正常处理了 |
204 | No Content | 该状态码表明服务器接收的请求已成功处理,但在返回的响应报文中不含实体的主体部分。另外,也不容许返回任何实体的主体。 |
301 | Moved Permanently | 永久重定向,该状态码表示请求的资源已被分配了新的 URI,之后应使用资源如今所指的 URI |
302 | Found | 临时性重定向,该状态码表示请求的资源已被分配了新的 URI,但愿用户(本次)能使用新的 URI 访问 |
303 | See Other | 303 状态码和 302 Found 状态码有着相同的功能,但 303 状态码明确表示客户端应当采用 GET 方法获取资源,这点与 302 状态码有区别 |
304 | Not Modified | 缓存 |
307 | Temporary Redirect | 临时重定向,和302同样 |
400 | Bad Request | 该状态码表示请求报文中存在语法错误。当错误发生时,需修改请求的内容后再次发送请求。另外,浏览器会像 200 OK 同样对待该状态码 |
401 | Unauthorized | 该状态码表示发送的请求须要有经过 HTTP 认证(BASIC 认证、DIGEST 认证)的认证信息 |
403 | Forbidden | 该状态码代表对请求资源的访问被服务器拒绝了 |
404 | Not Found | 该状态码代表服务器上没法找到请求的资源 |
500 | Internal Server Error | 该状态码代表服务器端在执行请求时发生了错误。也有多是 Web应用存在的 bug 或某些临时的故障 |
502 | Bad Gateway | 网关错误 |
503 | Service Unavailable | 该状态码代表服务器暂时处于超负载或正在进行停机维护,如今没法处理请求。若是事先得知解除以上情况须要的时间,最好写入RetryAfter 首部字段再返回给客户端 |
跨域资源共享( CORS) 是一种机制,它使用额外的 HTTP 头来告诉浏览器 让运行在一个 origin (domain) 上的Web应用被准许访问来自不一样源服务器上的指定的资源。当一个资源从与该资源自己所在的服务器不一样的域、协议或端口请求一个资源时,资源会发起一个跨域 HTTP 请求。 --MDN
下面使用nodejs来搭建一个简单的服务器,来介绍一个跨域问题的解决方法
// index.html <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>CORS</title> </head> <body> Hello World <script> fetch('http://127.0.0.1:8081') </script> </body> </html>
// server.js const http = require('http') http.createServer(function(req, res) { res.writeHead('200', { 'Access-Control-Allow-Origin': 'http://localhost:8082' }) }).listen(8081)
在源地址为 http://localhost:8082 下,请求http://localhost:8081,是跨域请求,浏览器会自动在request Header中发送Origin首部字段,并把值设置为来自哪一个源,本例为http://localhost:8082。服务器须要在响应头中设置Access-Control-Allow-Origin,来告知浏览器能够处理返回的数据。若是响应头中不设置Access-Control-Allow-Origin则会报错,可是返回状态码为200,跨域其实是浏览器自己的一个安全机制。
// server2.js // 启动8082端口服务,在浏览器中访问http://127.0.0.1:8082,会返回index.html内容 const http = require('http') const fs = require('fs') http.createServer(function(req, res) { var page = fs.readFileSync('index.html', 'utf-8') res.writeHead(200, { 'Content-Type': 'text/html' }) res.end(page) }).listen(8082)
关于CORS跨域请求的分类:
1.简单请求:
须要同时知足如下的条件就是简单请求
(1)请求方法:
GET、POST、HEAD
(2)请求头不能为如下其余字段以外
Accept Accept-Language Content-Language Content-Type的值必须为application/x-www-form-urlencoded、multipart/form-data、text/plain之一
2.非简单请求:
非简单请求是当请求信息不知足简单请求的条件,浏览器就发送方法为OPTIONS的预请求,包含本身请求的方法及须要使用的请求头字段,在获得服务器响应容许以后,浏览器会按照想要使用的请求方法及头信息再发一次请求。
如今修改如下上面的例子:
// index.html <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>CORS</title> </head> <body> Hello World <script> fetch('http://127.0.0.1:8081', { method: 'PUT', headers: { X-Coustom-Head: 'abc' } }) </script> </body> </html>
// server.js const http = require('http') http.createServer(function(req, res) { res.writeHead('200', { 'Access-Control-Allow-Origin': 'http://localhost:8082' }) }).listen(8081)
若是服务端不进行相应的设置告诉浏览器容许跨域访问则会报错
可是预请求返回状态码为200
// server2.js // 启动8082端口服务,在浏览器中访问http://127.0.0.1:8082,会返回index.html内容 const http = require('http') const fs = require('fs') http.createServer(function(req, res) { var page = fs.readFileSync('index.html', 'utf-8') res.writeHead(200, { 'Content-Type': 'text/html' }) res.end(page) }).listen(8082)
如今咱们修改如下 server.js
// server.js const http = require('http') http.createServer(function(req, res) { res.writeHead('200', { 'Access-Control-Allow-Origin': 'http://localhost:8082', 'Access-Control-Allow-Headers': 'X-Coustom-Head', 'Access-Control-Allow-Methods': 'PUT' }) }).listen(8081)
从新启动node服务,访问http://locaohost:8082,能够看到在发送预请求后,浏览器会继续发送PUT请求
关于CORS的其余设置这里就很少作介绍了,这里主要是用一个例子来讲明如下http不一样字段在跨域场景下的做用。
本例依旧用node服务来说解一下Cache-Control的做用,新建三个文件
// index.html <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>Cache-Control</title> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <script src="/script.js"></script> </body> </html>
// script.js console.log('script.js')
// server.js const http = require('http') const fs = require('fs') http.createServer(function(req, res) { if (req.url === '/') { let page = fs.readFileSync('index2.html', 'utf-8') res.writeHead(200, { 'Content-Type': 'text/html' }) res.end(page) } if (req.url === '/script.js') { let page = fs.readFileSync('script.js', 'utf-8') res.writeHead(200, { 'Content-Type': 'text/javascript', 'Cache-Control': 'max-age=10' }) res.end(page) } }).listen(8082)
在第一次请求script.js资源时,向服务器发送请求
因为服务器返回响应时,设置Cache-Control: 'max-age=10'时,修改script.js后,在10秒内继续请求script.js资源,则从缓存中读取,而打印信息依旧是'script.js'
// script.js console.log('script-modify.js')
更多关于缓存的知识在这里也很少介绍了,贴两张cache-control字段在请求和响应时能够设置的值和其表示含义:
1. Cache-Control 缓存请求指令:
2. Cache-Control 缓存响应指令:
指某些网站为了辨别用户身份、进行 session 跟踪而储存在用户本地终端上的数据(一般通过加密),当下次再访问时浏览器会将该网站的cookie发回给服务器端。
cookie若是不设置过时时间,随浏览器关闭而失效,若是有须要能够设置过时时间,继续上代码例子🌰,新建两个文件以下
// index.html <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>Cookie</title> </head> <body> Cookie <script> console.log(document.cookie) </script> </body> </html>
// server.js const http = require('http') const fs = require('fs') http.createServer(function(req, res) { if (req.url === '/') { let page = fs.readFileSync('index.html', 'utf-8') res.writeHead(200, { 'Content-Type': 'text/html', 'Set-Cookie': ['a=1;max-age:5', 'b=2;HTTPOnly'] }) res.end(page) } }).listen(8082)
启动node服务,访问localhost:8082,能够看到成功设置了cookie
并在响应头信息中设置了Set-Cookie字段
另外关注如下打印信息,发现只有a=1,由于给b=2设置了HttpOnly属性,不容许JavaScript经过脚原本获取到cookie信息
因为当再次请求时,cookie会在请求头中发送到服务器,因为cookie a=1设置了5秒后过时,在5秒后刷新页面,请求头中的cookie只有a=1
在5秒内发送二次请求,cookie a=1没有失效,在请求头中cookie a=1;b=2都会发送到服务器
另外对于cookie的其余设置如expires、domain等在这里也很少作介绍了
当服务端返回30一、30二、307等状态码都表明资源已经被重定向到其余位置,301表示永久改变URI,302和307表示临时重定向到某个URI
本例举一个服务器返回302状态码的例子,直接上代码:
// server.js const http = require('http'); const fs = require('fs') http.createServer((req, res) => { if (req.url === '/') { res.writeHead(302, { 'Location': '/redirect' }) res.end() } if (req.url === '/redirect') { res.end('redirect') } }).listen(8082);
访问localhost:8082, 服务器返回302状态码时,在相应头中设置Location首部字段,浏览器会继续发送请求到重定向的地址
首先说一下什么是HTTPS
HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer 或 Hypertext Transfer Protocol Secure,超文本传输安全协议),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。即HTTP下加入SSL层,HTTPS的安全基础是SSL,所以加密的详细内容就须要SSL。 --百度百科
HTTPS = HTTP+ 加密 + 认证 + 完整性保护
最主要是在应用层和传输层中间加了一个SSL(安全套阶层),一般,HTTP 直接和 TCP 通讯。当使用 SSL 时,则演变成先和 SSL 通讯,再由 SSL 和 TCP 通讯。
HTTP与HTTPS的区别:
本文主要介绍HTTP,关于HTTPS主要就介绍这么多吧。
本想说点HTTP2的知识,奈何本身是小白,放个百度百科的连接吧 HTTP2。
等后续随着不断的学习,再回来更新本文。
另外放一个HTTP1.1与HTTP2请求与相应对比的demo的连接HTTP/2 is the future of the Web, and it is here!
最后,本文主要介绍了一些HTTP在web开发中的基础知识,关于概念和图解流程的截图基本上都是来自《TCP/IP详解 卷1:协议》、《图解HTTP》、《HTTP权威指南》,可放心参考。笔者功力实在有限,若有问题,请你们多多指出,相互学习和进步,也但愿经过个人学习与实践过程,整理出的笔记能对你们有所帮助,谢谢。
本文参考连接: