- HTTP 基础
- 1. 介绍
- 1.1 概述
- 1.2 特点
- 1.3 URL
- 2. 发展历程
- 3. 消息结构
- 3.1 客户端请求消息
- 3.1.1 请求方法
- 3.2 服务端响应消息
- 3.2.1 状态码
- 4. 跨域
- 4.1 产生原因
- 4.2 解决办法
- HTTP 协议是 Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网( WWW:World Wide Web )服务器传输超文本到本地浏览器的传送协议
- HTTP 是基于 TCP/IP 通信协议来传递数据(HTML 文件、图片文件、查询结果等)
- HTTP 协议工作于客户端-服务端架构上。浏览器作为 HTTP 客户端通过 URL 向 HTTP 服务端即 WEB 服务器发送所有请求
Web 服务器有:Apache 服务器,IIS 服务器(Internet Information Services)等
Web 服务器根据接收到的请求后,向客户端发送响应信息
HTTP 默认端口号为 80,但是可以改为 8080 或者其他端口
- 简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、POST。每种方法规定了客户与服务器联系的类型不同。由于 HTTP 协议简单,使得 HTTP 服务器的程序规模小,因而通信速度很快
- 灵活:HTTP 允许传输任意类型的数据对象。正在传输的类型由 Content-Type 加以标记。这意味着,只要客户端和服务器知道如何处理的数据内容,任何类型的数据都可以通过 HTTP 发送。客户端以及服务器指定使用适合的 MIME-type 内容类型
- 无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间
- 无状态:HTTP 协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快
- 支持 B/S 及 C/S 模式
HTTP 使用统一资源标识符(Uniform Resource Identifiers, URI)来传输数据和建立连接。URL 是一种特殊类型的URI,包含了用于查找某个资源的足够的信息
URL ,全称是 Uniform Resource Locator ,中文叫统一资源定位符,是互联网上用来标识某一处资源的地址
http://www.test.com:8080/news/index.asp?boardID=5&ID=24618&page=1#name
- 协议部分:http:,代表网页使用的是 HTTP 协议。在 Internet 中可以使用多种协议,如HTTP,FTP 等等。在http:后面的//为分隔符
- 域名部分:www.test.com。在 URL 中,也可以使用 IP 地址作为域名使用
- 端口部分:8080,域名之后是端口,域名和端口之间使用:作为分隔符。非必须,如果省略端口部分,将采用默认端口 80
- 虚拟目录部分:/news/,从域名后的第一个/开始到最后一个/为止,是虚拟目录部分。非必须
- 文件名部分:index.asp,从域名后的最后一个/开始到?为止,是文件名部分,如果没有?,则是从域名后的最后一个/开始到#为止,是文件部分,如果没有?和#,那么从域名后的最后一个/开始到结束,都是文件名部分。非必须,如果省略该部分,则使用默认的文件名
- 锚部分:name,从#开始到最后,都是锚部分。非必须
- 参数部分:boardID=5&ID=24618&page=1,从?开始到#为止之间的部分为参数部分,又称搜索部分、查询部分。参数部分可以允许有多个参数,参数与参数之间用&作为分隔符
URI 和 URL 的区别比较与理解
2. 发展历程- 超文本传输协议的前身是世外桃源(Xanadu)项目,超文本的概念是泰德˙纳尔森(Ted Nelson)在 1960 年代提出的。进入哈佛大学后,纳尔森一直致力于超文本协议和该项目的研究,但他从未公开发表过资料。1989 年,蒂姆˙伯纳斯˙李(Tim Berners Lee)在 CERN (欧洲原子核研究委员会 = European Organization for Nuclear Research)担任软件咨询师的时候,开发了一套程序,奠定了万维网(WWW = World Wide Web)的基础。1990 年 12 月,超文本在 CERN 首次上线。1991 年夏天,继 Telnet 等协议之后,超文本传输协议成为互联网诸多协议的一分子
- 当时,Telnet 协议解决了一台计算机和另外一台计算机之间一对一的控制型通信的要求。邮件协议解决了一个发件人向少量人员发送信息的通信要求。文件传输协议解决一台计算机从另外一台计算机批量获取文件的通信要求,但是它不具备一边获取文件一边显示文件或对文件进行某种处理的功能。新闻传输协议解决了一对多新闻广播的通信要求。而超文本要解决的通信要求是:在一台计算机上获取并显示存放在多台计算机里的文本、数据、图片和其他类型的文件;它包含两大部分:超文本传输协议和超文本标记语言(HTML)。HTTP、HTML 以及浏览器的诞生给互联网的普及带来了飞跃
| 版本 | 产生时间 | 内容 | 发展现状 |
|---|---|---|---|
| HTTP/0.9 | 1991 年 | 不涉及数据包传输,规定客户端和服务器之间通信格式,只能 GET 请求 | 没有作为正式的标准 |
| HTTP/1.0 | 1996 年 | 传输内容格式不限制,增加PUT、PATCH、HEAD、 OPTIONS、DELETE命令 | 正式作为标准 |
| HTTP/1.1 | 1997 年 | 持久连接(长连接)、节约带宽、HOST域、管道机制、分块传输编码 | 2015年前使用最广泛 |
| HTTP/2 | 2015 年 | 多路复用、服务器推送、头信息压缩、二进制协议等 | 逐渐覆盖市场 |
| HTTP/3 | 2018 年 | 使用 UDP 取代 TCP 协议,解决丢包问题 | 已被 Chrome,Firefox,和 Cloudflare 支持 |
客户端发送一个 HTTP 请求到服务器的请求消息:请求行(request line)、请求头部(header)、空行和请求数据四个部分组成
第一部分:请求行,用来说明请求类型,要访问的资源以及所使用的 HTTP 版本
第二部分:请求头部,紧接着请求行(即第一行)之后的部分,用来说明服务器要使用的附加信息
- Accept : 客户端希望接受的数据类型,比如 Accept:text/xml(application/json)表示希望接受到的是 xml(json)类型
- Referer:表示请求是从哪个 URL 进来的,例如在百度上点击链接到了这里,那么 Referer:http://www.baidu.com ;如果是在浏览器的地址栏中直接输入的地址,那么就没有Referer 这个请求头了
- Accept-Language:当前客户端支持的语言
- User-Agent : 客户端使用的操作系统、浏览器版本和名称
- Content-Type:客户端发送的实体数据的数据类型。比如,Content-Type:text/html 表示发送的是 html 类型
- Host:请求的主机名和端口号
- Content-Length:请求体的长度(字节)
- Connenction:客户端支持的链接方式,Connection::keep-alive,保持一段时间链接,默认为 3000ms
- Cache-Control:缓存控制
- Cookie:因为不是第一次访问这个地址,所以会在请求中把上一次服务器响应中发送过来的 Cookie 在请求中一并发送过去
- Accept-Encoding:客户端支持的编码方式
第三部分:空行,请求头部后面的空行是必须的
第四部分:请求数据也叫主体,可以添加任意的其他数据
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 方法的补充,用来对已知资源进行局部更新 |
一般情况下,服务器接收并处理客户端发过来的请求后会返回一个 HTTP 的响应消息
HTTP 响应也由四个部分组成,分别是:状态行、消息报头、空行和响应正文
第一部分:状态行,由 HTTP 协议版本号, 状态码, 状态消息 三部分组成
第二部分:消息报头,用来说明客户端要使用的一些附加信息
- Server:服务器名字及版本信息。Servlet 一般不设置这个值,而是由 Web 服务器自己设置
- Content-Type:表示后面的文档属于什么 MIME 类型。Servlet 默认为 text/plain,但通常需要显式地指定为 text/html。由于经常要设置 Content-Type,因此HttpServletResponse 提供了一个专用的方法 setContentType
- Transfer-Encoding:传输遵循的数据传输机制
- Date:当前的 GMT 时间。可以用 setDateHeader 来设置这个头以避免转换时间格式的麻烦
- Allow:服务器支持哪些请求方法(如 GET、POST 等)
- Content-Encoding:文档的编码(Encode)方法
- Content-Length:表示内容长度
- Expires:什么时候过期
- Last-Modified:文档的最后改动时间。可以通过 If-Modified-Since 请求头提供一个日期,该请求将被视为一个条件 GET,只有改动时间迟于指定时间的文档才会返回,否则返回一个 304(Not Modified)状态。Last-Modified 也可用 setDateHeader 方法来设置
- Location:表示应到哪里去获取资源。Location 通常不是直接设置的,而是通过 HttpServletResponse 的 sendRedirect 方法,该方法同时设置状态代码为 302
- Refresh:表示浏览器应该在多少时间之后刷新文档,以秒计。Refresh 头不属于 HTTP 1.1 正式规范的一部分,而是一个扩展,但 Netscape 和 IE 都支持它
- Set-Cookie:设置和页面关联的 Cookie。Servlet 不应使用 response.setHeader(“Set-Cookie”, …) ,而是应使用 HttpServletResponse 提供的专用方法 addCookie
- WWW-Authenticate:应该在 Authorization 头中提供什么类型的授权信息,在包含401(Unauthorized)状态行的应答中这个头是必需的。例如,response.setHeader(“WWW-Authenticate”, “BASIC realm=\“executives\””)。
注意 Servlet 一般不进行这方面的处理,而是让 Web 服务器的专门机制来控制受密码保护页面的访问(例如 .htaccess)
第三部分:空行,消息报头后面的空行是必须的
第四部分:响应正文,服务器返回给客户端的文本信息
HTTP 状态码的英文为 HTTP Status Code
| 状态码 | 类别 | 解释 |
|---|---|---|
| 1XX | Informational 信息提示 | 请求正在处理 |
| 2XX | Success 成功 | 请求处理成功 |
| 3XX | Redirection 重定向 | 需要进行额外操作 |
| 4XX | Client Error 客户端错误 | 含有词法错误或者无法被执行 |
| 5XX | Server Error 服务器错误 | 服务器处理请求出错 |
常用状态码
- 100 Continue
用于通知客户端继续。若请求只发送了一部分,那么该部分的请求服务器已经接受后,返回 100 告知客户端继续发送请求剩余部分 - 200 OK
请求响应成功,返回 200 - 400 Bad Request
一般可能请求方法错误,要求的是 GET,结果请求用了 POST。请求存在语法错误,需要修改请求后再尝试 - 404 Not Found
找不到请求的资源,也就是服务器没有这个资源,所以请求不到,也可以在服务器拒绝请求时使用 - 505 Internal Server Error
服务器内部错误,就要看看代码是否出错,是不是哪里报空指针,或者数据类型不匹配之类的。(debug…) - 503 Service Unavailable
服务器不可用。服务器由于临时的服务器过载或者是维护,无法响应当前请求
由于浏览器的同源策略限制,浏览器会拒绝跨域请求
同源策略是 Web 的一种安全约定,浏览器的同源策略只是对其的一种实现
浏览器同源策略将认为任何站点装载的内容都是不安全的。所以会对跨域的操作或者请求进行限制,从而让用户安全的上网
- 同源
如果两个页面的协议,域名,端口都相同,则两个页面具有相同的源。如果三者种有一个不同,则视为非同源,即跨域
| 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 | 端口不同 |
允许跨域资源共享(CORS:Cross- Origin Resource Sharing)
CORS
CORS 使用额外的 HTTP 头部信息来告诉浏览器,让在一个 origin 域上的 web 应用被允许访问来自不同 origin 服务器上的指定的资源
- CORS 是一个 W3C 标准,该标准定义了在访问跨域资源时,服务端和客户端需要如何沟通,如何授权信任。所有的浏览器都支持该标准,由浏览器自动完成
- CORS 的原理是:使用 HTTP 自定义头部 ,请求头附带客户端信息,服务端验证,并且返回响应头告诉客户端是否允许访问,只需要由服务端改动,前端不需要改动
CORS 将 HTTP 请求分为简单请求和非简单请求:
简单请求:不会发送 CORS 预检请求的请求
必须满足3个条件
- 请求方法为 HEAD、GET、POST 中的一种
- HTTP 的请求头不超过以下 4 种字段 Accept、Accept-Language、Content-Language、Content-Type
- 其中 Content-Type 的值,只能取 application/x-www-form-urlencoded、multipart/form-data、text/plain 三个中的一个
解决步骤
- step1:
浏览器在 HTTP 头部带上 Origin(原始域),表明可以访问该资源的域名,只能是单个域名或者 *
Access-Control-Allow-Origin:https://www.baidu.com
!注意:只有跨域请求,或者同域时发送post请求,才会携带origin请求头
- step2:
如需使用 cookies
前端:ajax 的 withCredentials 设置为 true
服务端: 响应头增加 Access-Control-Allow-Credentials: true(可选)
//允许跨域的域名,*号为允许所有。解决跨域访问报错
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
//将Cookie发到服务端,需要指定Access-Control-Allow-Credentials为true;
response.setHeader("Access-Control-Allow-Credentials", "true");
非简单请求:会发送 CORS 预检请求的请求
- 预检请求
- 在真正发送请求前,先发一个询问请求过去,用于询问服务端是否支持非简单请求
- 预检请求的请求方式是 OPTIONS ,其请求头必须包含origin,以及两个特殊字段 Access-Control-Request-Method, Access-Control-Request-Headers
| 字段 | 说明 |
|---|---|
| Access-Control-Request-Method | 列出浏览器 CORS 请求会用的一些 HTTP 请求方法 |
| Access-Control-Request-Headers | 用一个逗号,分隔的字符串,指定浏览器 CORS 请求会额外发送的请求头字段 |
- 预检请求响应
- 预检响应失败,返回正常 HTTP 响应,不涉及 CORS 的头部字段
包含的几个重要字段:
(1)Access-Control-Allow-Methods:服务器支持的所有跨域请求的方法
(2)Access-Control-Allow-Headers:如果浏览器请求包括 Access-Control-Request-Headers 字段,则 Access-Control-Allow-Headers 字段是必需的。它也是一个逗号分隔的字符串,表明服务器支持的所有头信息字段
(3)Access-Control-Max-Age(可选):响应有效时间,即响应的保存时间,过期了需要重新请求
Access-Control-Allow-Origin 、Access-Control-Allow-Credentials(同上简单请求)
//允许跨域的域名,*号为允许所有。解决跨域访问报错
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");



