HTTP基础
一、概述
1.1 什么是协议
- 协议实际上是某些人,或者某些组织提前制定好的一套规范,大家都按照这个规范来,这样可以做到沟通无障碍。
- 协议就是一套规范,就是一套标准。由其他人或其他组织来负责制定的。
- 我说的话你能听懂,你说的话,我也能听懂,这说明我们之间是有一套规范的,一套协议的,这套协议就是∶中国普通话协议。我们都遵守这套协议,我们之间就可以沟通无障碍。
1.2 什么是HTTP协议
- HTTP协议:HTTP 协议是 Hyper Text Transfer Protocol的缩写,是W3C制定的一种超文本传输协议。(通信协议:发送消息的模板提前被制定好。)
- 什么是超文本?
- 超文本说的就是:不是普通文本,比如流媒体:声音、视频、图片等。
- HTTP协议支持:不但可以传送普通字符串,同样支持传递声音、视频、图片等流媒体信息。
1.3 URL
-
我们平时说的网址,其实就是指的URL(Uniform Resource Locator),翻译为统一资源定位符
-
URL是对互联网上得到的资源的位置和访问方法的一种简洁表示,是互联网上标准资源的地址。URL它具有全球唯一性,正确的URL应该是可以通过浏览器打开此网页的,但如果您访问外网,会提示网页无法打开,这并不能说明这个URL是错误的。只不过在国内不能访问而已。
-
URL标准格式
协议类型:[//服务器地址[:端口号]][/资源层级 UNIX 文件路径]文件名[?查询字符串][#片段标识符]
-
URL完整格式
协议类型:[//服务器地址[:端口号]][/资源层级 UNIX 文件路径]文件名[?查询字符串][#片段标识符]
-
例子
https://blog.csdn.net/qq_64452847/article/details/130373931
-
参数介绍
信息 | 描述 | 可否省略 |
---|---|---|
协议类型 | 常见的协议类型有 http 和 https,访问 mysql 时的协议类型为 jdbc:mysql | 可省略,省略后默认为 http:// |
访问资源需要的凭证信息 | 一般就是登录信息(用户名、密码等),但是现在的网站进行认证一般不再通过 URL 进行,故一般省略 | 可以省略 |
服务器地址 | 服务器的地址可以时一个 IP 地址,也可以是一个域名 | 在 HTML 中可以省略(比如 img、link、script、a 标签的 src 或者 href 属性),省略后表示服务器的 ip 或域名与当前 HTML 所属的 ip 或域名一致 |
端口号 | 端口号的主要作用是表示一台计算机中的特定进程所提供的服务,即用来区分一个主机上的不同程序。每个程序在访问网络的时候,都会关联上一个或多个端口号,通过端口号就能区分出当前的请求要给谁。 | 可以被省略,当端口号省略时,浏览器会根据协议类型自动决定使用哪个端口号(如 http 协议默认使用80端口,https 协议默认使用443端口) |
资源层级 UNIX 文件路径 | 表示访问该服务器程序上某个资源的路径 | 可以省略,省略后相当于 / |
文件名 | 表示访问该服务器上的哪个资源(如 html、图片等等) | 不能省略 |
查询字符串 | 查询字符串(query string)本质是一个键值对结构,且键值对之间使用 & 分割,键和值之间使用 = 分割。表示客户端给服务器传递的参数。该参数是 web 开发的一个重要参数,给前后端交互提供了很多可能性。该参数 key 和 value 的取值和个数,完全都是由程序员自己约定,因此可以通过这样的方式来自定制我们需要的信息给服务器 | 可以省略 |
片段标识符 | 片段标识符主要用于页面内跳转,例如跳转到当前页面的某个部分、章节等等 | 可以省略 |
二、请求报文
2.1 报文格式
- GET请求具体报文
GET /example/path?key1=value1&key2=value2 HTTP/1.1 请求行
Host: www.example.com 请求头
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.164 Safari/537.36
Accept: text/html,application/xhtml+xml
Accept-Language: en-US,en;q=0.5
Connection: keep-alive
Referer: https://www.google.com/
空白行
请求体
- POST请求具体报文
POST /submit-form HTTP/1.1 请求行
Host: www.example.com 请求头
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.164 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Content-Length: 27
Connection: keep-alive
Referer: https://www.example.com/form-page
空白行
key1=value1&key2=value2 请求体
2.1.1 请求行
- 第一部分:请求方式
- get
- post
- delete
- put
- head
- options
- trace
- 第二部分:URI
- 统一资源标识符,标识某个资源
- 第三部分:协议版本号
2.1.2 请求头
- 请求的主机
- 主机的端口
- 浏览器信息
- 平台信息
- cookie
- …
2.1.3 空白行
- 区分请求头和请求体
2.1.4 请求体
- 向服务器具体发送的信息
2.2 请求方法
-
HTTP1.0 定义了三种请求方法: GET, POST 和 HEAD 方法
-
HTTP1.1 新增了五种请求方法:OPTIONS, PUT, DELETE, TRACE 和 CONNECT 方法
方法 | 描述 |
---|---|
GET | 获取服务器资源,参数直接附带在 URL 后面 |
HEAD | 类似于 GET 请求,只不过返回的响应中没有具体的内容,主要用于测试超链接的有效性等 |
POST | 更新服务器资源(application/x-www-form-urlencoded用来传输简单的数据,multipart/form-data格式用于传文件)。数据被包含在请求体中。POST 请求可能会导致新的资源的建立和/或已有资源的修改 |
PUT | 向指定资源位置上传其最新内容。不同于 POST 接收到服务器发送的请求后,可以对请求数据作出处理后,应用到多个资源上;而 PUT 限定了这个请求数据只能应用到指定的位置上 |
DELETE | 请求服务器删除指定的资源 |
CONNECT | HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器 |
OPTIONS | 可使服务器传回该资源所支持的所有 HTTP 请求方法。用’*'来代替资源名称,向 Web 服务器发送 OPTIONS |
TRACE | 回显服务器收到的请求,主要用于测试或诊断 |
PATCH | 是对 PUT 方法的补充,用来对已知资源进行局部更新 |
三、响应报文
响应报文由服务器发送给客户端,用于回应客户端发起的请求
3.1 报文格式
HTTP/1.1 200 OK //状态行
Content-Type: text/html; charset=utf-8 //响应头
Content-Length: 1234
Date: Wed, 28 Jul 2023 12:34:56 GMT
Server: Apache/2.4.38 (Unix)
//空白行
<!DOCTYPE html> //响应体
<html>
<head>
<title>示例网页</title>
</head>
<body>
<h1>Hello, World!</h1>
<p>This is an example webpage.</p>
</body>
</html>
3.1.1 状态行
- 第一部分:协议版本号(HTTP/1.1)
- 第二部分:状态码
- 200 响应成功,正常结束
- 404 访问的资源不存在,通常是因为路径写错了,或者服务器中对应的资源没有成功启动
- 405 表示发送的请求方式与后端处理的请求方式不一致
- 500 表示服务器端的程序出现了异常,一般认为是服务器端的我呢提
- 以4开始的,一般是浏览器端的问题导致的
- 以5开始的,一般是服务器端的问题导致的
- 第三部分:状态描述信息
3.1.2 响应头
- 响应的内容类型
- 响应的内容长度
- 响应的时间
- …
3.1.3 空白行
用来分隔“响应头”和“响应体”
3.1.4 响应体
响应体就是响应的正文,这些内容是一个长的字符串,这个字符串被浏览器渲染,解释并执行,最终展示出效果。
3.2 状态码
状态码 | 类别 | 解释 |
---|---|---|
1XX | Informational 信息提示 | 请求正在处理 |
2XX | Success 成功 | 请求处理成功 |
3XX | Redirection 重定向 | 需要进行额外操作 |
4XX | Client Error 客户端错误 | 含有词法错误或者无法被执行 |
5XX | Server Error 服务器错误 | 服务器处理请求出错 |
四、跨域
4.1 介绍
-
什么是跨域?
- 顾名思义,跨域就是两个不同的域,从一个域跨到另一个域,这里的跨指的是访问某个资源。即,从一个域名的网页去访问/请求另一个域名的资源称为跨域。
-
怎样才算不同的域呢?
- 满足以下任意一点的两个URL都是不同的域,即不同源
- 协议不同
- 主机不同
- 端口不同
- 例子
url 1(请求页面) url 2(被请求页面) 是否跨域 http://www.baidu.com:8080 http://www.baidu.com:8080?p=tom 否,三者都相同 http://www.baidu.com:8080 https://www.baidu.com:8080 协议不同 http://www.baidu.com:8080 http://www.google.com:8080 域名不同 http://www.baidu.com:8080 http://www.baidu.com:8082 端口不同 - 满足以下任意一点的两个URL都是不同的域,即不同源
4.2 问题
- 跨域会出问题吗?会出什么问题?为什么会出问题?
-
会。会报如下错误。报错原因是浏览器的同源策略
-
同源策略(Same Origin Policy)是一种约定,它是浏览器最核心也是最基本的安全功能。同源策略会阻止一个域的javascrip脚本和另一个域的内容进行交互,是用于隔离潜在恶意文件的关键安全机制;关于这一点我们后面会举例说明。如果缺少了同源策略浏览器的安全使用会受到很大的影响。可以说web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。
-
- 所有的跨域访问都会出问题吗?
- 不是。
- 通过超链接,form表单提交,window.location.href跨域访问,以及使用img,script,style跨域引用资源不会出问题。但是使用js代码发送ajax跨域请求时,就会出现问题
4.3 解决问题
- 解决跨域问题有如下几种方式:
- CORS
- jsonp
- 代理机制(httpclient)
- nginx反向代理
- 我们讲解第一种(简单,只需要后端设置几行代码),其他几种方式有兴趣的可以去自行了解
-
什么是CORS
- Cross-Origin Resource Sharing的缩写,即跨域资源共享,简称为跨域访问,允许 Web 应用服务器进行跨域访问控制,从而使跨域数据传输得以安全进行。CORS 需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE 浏览器要求版本 IE10 或以上。
整个 CORS 通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS 通信与同源的 AJAX 通信没有差别,代码完全一样。浏览器一旦发现 AJAX 请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户无感知。
因此,实现 CORS 通信的关键是服务器。只要服务器实现了 CORS 接口,即可跨源通信
- Cross-Origin Resource Sharing的缩写,即跨域资源共享,简称为跨域访问,允许 Web 应用服务器进行跨域访问控制,从而使跨域数据传输得以安全进行。CORS 需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE 浏览器要求版本 IE10 或以上。
-
CORS原理
-
先看看前面跨域的报错信息
-
浏览器判断后端有没有返回CORS头(Access-Control-Allow-Origin),发现没有就认为后端不允许跨域,即认为返回的数据不可靠。
所以只要后端能够返回浏览器需要响应头,即可跨域(相应数据不会被同源策略抛弃)。
上面是表面原理,底层原理比较复杂。
浏览器会将ajax请求分为两类,其处理方案略有差异:简单请求、特殊请求。 -
简单请求,直接发送实际请求,会在请求头携带一个字段origin,其值为当前页面所属的域,满足以下条件
- 请求方法是以下三种方法之一:
- HEAD
- GET
- POST
- HTTP的头信息不超出以下几种字段:
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
- 示例
- 请求方法是以下三种方法之一:
-
特殊请求,就是非简单请求,在发送实际请求之前,会先使用OPTIONS方法发送一个预检请求到服务器,以获知服务器是否允许该实际请求。"预检请求“的使用,可以避免跨域请求对服务器的用户数据产生未预期的影响。
-
示例
- 两个请求
- 预检请求
- 实际请求
- 两个请求
-
-
-
CORS实现
- 其实非常简单,对于简单请求,只需要后端一行代码:
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
- 什么意思呢?就是给响应头加一个字段”Access-Control-Allow-Origin“,告诉浏览器哪些源可以访问本服务器中的资源,”request.getHeader(“Origin”)“就是允许发送此请求的源访问,也可以直接写”*“
- 对于特殊请求,还需要加如下代码
response.setHeader("Access-Control-Allow-Headers","Content-type");
- 就是再给响应头加一个字段"Access-Control-Allow-Headers",告诉浏览器本服务器允许哪些响应头字段,后面的值可以用逗号隔开写很多,前端设置了什么头字段写什么字段就行。
-
4.4 跨域总结
- 是不是看到前面劈里啪啦这么多,头都大了,其实也不用看(最好还是看看,毕竟我打了这么久),把下面代码ctrl c/v到代码里面就完事儿了,要是有啥bug,而且还解决不了,记得呼叫学长学姐
//允许跨域的域名,*号为允许所有。解决跨域访问报错
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
//服务器支持的所有头信息字段
response.setHeader("Access-Control-Allow-Headers",
"Origin," +
"Access-Control-Request-Headers," +
"Access-Control-Allow-Headers," +
"DNT," +
"X-Requested-With," +
"X-Mx-ReqToken," +
"Keep-Alive," +
"User-Agent," +
"X-Requested-With," +
"If-Modified-Since," +
"Cache-Control," +
"Content-Type," +
"Accept," +
"Connection," +
"Cookie," +
"X-XSRF-TOKEN," +
"X-CSRF-TOKEN," +
"Authorization");
//将Cookie发到服务端,需要指定Access-Control-Allow-Credentials为true;
response.setHeader("Access-Control-Allow-Credentials", "true");
//首部字段 Access-Control-Allow-Methods 表明服务器允许客户端使用 POST, GET 和 OPTIONS 方法发起请求
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
//设置过期时间,这里设置响应最大有效时间为 86400 秒,即24 小时
response.setHeader("Access-Control-Max-Age", "86400");