本文对 http 协议中一些基础知识的概括和总结:
WWW由三项技术组成
- HTML(超文本标记语言)
- HTTP(文档传输协议)
- URL(统一资源定位符)
URI与URL
-
URI(Uniform Resource Identifier):统一资源标志符
-
URL(Uniform Resource Loator):统一资源定位符
-
URI是用来标记某一互联网资源的,而URL表示网络资源的位置,也是一种URI,所以URL是URI的子集
-
URI的格式:
-
片段标志符:URL中任一带#的后面部分称为片段标志符,也称URL hash
- 片段标志符表示资源内的某一个位置,HTML文档里,浏览器会寻找该标志符对应的<a>标签
- 片段标志符只会被浏览器识别,不会发送给服务端
- 修改片段标志符不会重新加载页面,但会增加一条浏览器的历史记录
- javascript可以通过window.location.hash修改片段标志符
- Data URI:以data开始的协议头,常被用于作为小文件插入到其他文档之中,由四部分组成:
data:image/gif;base64,R0lGODlhEAAOALMAAOazToeHh0tLS/7LZv/0jvb29t/f3//Ub//ge8WSLf/rhf/3kdbW1mxsbP//mf///yH5BAAAAAAALAAAAAAQAA4AAARe8L1Ekyky67QZ1hLnjM5UUde0ECwLJoExKcppV0aCcGCmTIHEIUEqjgaORCMxIC6e0CcguWw6aFjsVMkkIr7g77ZKPJjPZqIyd7sJAgVGoEGv2xsBxqNgYPj/gAwXEQA7
- 第一部分是 data: 协议头
- 第二部分是 MIME 类型,表示这串内容的展现方式
- 第三部分是编码设置,默认编码是 charset=US-ASCII
- 最后一部分为这个 Data URI 承载的内容,它可以是纯文本编写的内容,也可以是经过base64编码的内容
- Javascript URI:以javascript开始的伪协议
当浏览器装载了这样的URL时,它将执行这个URL中包含的javascript代码,并把最后一条javascript语句的字符串值作为新文档的内容显示出来
装载了这种URL时,浏览器仅执行其中的javascript代码,但由于没有作为新文档来显示的值,因此它并不改变当前显示的文档。
javascript:var now = new Date(); "<h1>The time is:</h1>" + now;
javascript:alert("hello world!")
- CGI(Common Gateway Interface):公公网关接口
CGI(Common Gateway Interface) 是WWW技术中最重要的技术之一,有着不可替代的重要地位。CGI是外部应用程序(CGI程序)与WEB服务器之间的接口标准,
是在CGI程序和Web服务器之间传递信息的过程。CGI规范允许Web服务器执行外部程序,并将它们的输出发送给Web浏览器,CGI将Web的一组简单的静态超媒体
文档变成一个完整的新的交互式媒体
HTTP协议
Method详解
方法 | 说明 | 支持协议 |
---|---|---|
GET | 获取资源 | 1.0 , 1.1 |
POST | 传输实体文本 | 1.0,1.1 |
PUT | 传输文件 | 1.0 , 1.1 |
HEAD | 获取报文首部 | 1.0,1.1 |
DELETE | 删除资源 | 1.0 , 1.1 |
OPTIONS | 询问支持的方法 | 1.1 |
TRACE | 追寻路径 | 1.1 |
CONNECT | 以隧道协议连接代理 | 1.1 |
LINK | 建立与资源之间的连接 | 1.0 |
UNLINK | 断开连接 | 1.0 |
- GET方法:
GET 是最常用的方法。通常用于请求服务器发送某个资源
- HEAD方法:
HEAD方法与GET方法的行为很类似,但服务器在响应中只返回首部,不会返回实体的主体部分
- 在不获取资源的情况下了解资源的情况(比如,判断其类型);
- 通过查看响应中的状态码,看看某个对象是否存在;
- 通过查看首部,测试资源是否被修改了
- PUT方法:
用于更新资源的方法,使用PUT方法一般要遵循幂等性,所谓幂等性是指在多次调用同一方法时,资源的状态不变,不会受到其它接口的影响。所以使用PUT方法,每次更新要将资源的全部数据进行更新,全量覆盖。一般用于向服务器上的资源(例如文件)中存储数据
- POST方法:
用于更新资源的方法,使用POST不需要遵循幂等性,POST一般用于向服务器发送数据
- TRACE方法:
客户端发起一个请求时,这个请求可能要穿过防火墙、代理、网关或其他一些应用程序。每个中间节点都可能会修改原始的 HTTP 请求。TRACE 方法允许客户端在最终将请求发送给服务器时,看看它变成了什么样子。
- TRACE 方法主要用于诊断,可以用来查看代理和其他应用程序对用户请求所产生效果
- TRACE 请求中不能带有实体的主体部分
- TRACE 响应的实体主体部分包含了响应服务器收到的请求的精确副本
- OPTIONS方法:
OPTIONS 方法请求 Web 服务器告知其支持的各种功能。可以询问服务器通常支持哪些方法,或者对某些特殊资源支持哪些方法
一个使用场景就是”跨域非简单请求时“时,浏览器会先发一个OPTIONS请求来先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段
- DELETE方法:
顾名思义,DELETE 方法所做的事情就是请服务器删除请求 URL 所指定的资源,该方法也具有幂等性
- CONNECT方法:
CONNECT方法是HTTP/1.1协议预留的,能够将连接改为管道方式的代理服务器,实现隧道协议进行TCP通信,通常用于SSL加密服务器的链接与非加密的HTTP代理服务器的通信。
- PATCH方法:
PATCH方法出现的较晚,它在2010年的 RFC 5789 PATCH Method for HTTP标准中被定义。
PATCH请求与PUT请求类似,同样用于资源的更新。二者有以下两点不同:
- PATCH一般用于资源的部分更新,而PUT一般用于资源的整体更新。
- 当资源不存在时,PATCH会创建一个新的资源,而PUT只会对已在资源进行更新。
http keep-alive(长连接)
- 减少了TCP连接的重复建立和断开的造成的开销
- 减轻服务端压力
- http/1.1中默认所有连接都是长连接
http状态码详解
状态码范围 | 类别 | 作用 |
---|---|---|
1XX | 信息性 | 接收的请求正在处理 |
2XX | 成功 | 请求正常处理完毕 |
3XX | 重定向 | 需要进行附加操作以完成请求 |
4XX | 客户端错误 | 服务端无法处理请求 |
5XX | 服务端错误 | 服务端处理请求出错 |
- 200: success
- 204: No Content 成功状态响应码表示目前请求成功,但客户端不需要更新其现有页面。204 响应默认是可以被缓存的
- 206:Partial Content,客户端进行范围请求,客户端成功执行,范围请求需要包含Content-Range请求头部
- 301: Moved Permanently 永久重定向,表示请求的资源已经被分配到新的URL,GET方法不会变更,其它方法可能会变为GET方法,301重定向客户端会做缓存
- 302: Moved Temporarily 本次操作希望访问新的URL,GET方法不会变更,其它方法可能会变为GET方法
- 303: See Other 表示请求对应的资源存在另一个URL,应该使用get方法获取资源,GET 方法不会发生变更,其他方法会变更为 GET 方法(消息主体会丢失)
- 304: Not Modified 表示客户端发送附带条件的请求时,服务端允许请求访问资源,但未满足条件的情况。该状态码表示缓存值依然有效,可以使用
- 307: Multiple Choice 则是一种手工重定向,以 Web 页面形式呈现在浏览器中的消息主体包含了一个可能的重定向链接的列表,用户可以从中进行选择
- 308: Permanent Redirect 永久重定向,方法和消息主体都不发生变化,
- 400: Bad Request 表示请求报文中存在语法错误
- 401: UNAUTHORIZED 表示请求报文中缺少对于所请求资源的认证证书,服务端会返回一个WWW-Authenticate的响应头信息,表示需要的认证信息。如果客户端对于相同认证信息已经请求过一次,则表示用户认证失败
- 403: Forbidden 客户端的请求被服务器拒绝,一般是表示没有授权等情况
- 404: Not Found 表示在服务器上找不到请求资源
- 500: Internal Server Error 表示服务器内部错误,一般是服务器程序存在bug导致的
- 502: Bad Gateway 一般表示服务器挂了,然后网关或者代理服务器收不到响应而返回
- 503: Service Unavailable 由于当前服务器的负载比较大或者正在执行其它任务,所以无法处理当前请求返回,提示客户端稍后再做请求
- 504: Gateway Timeout 代理服务器在指定的时间内没有收到数据返回然后报错
- 505: HTTP Version Not Supported 客户端的http版本,服务端不支持,并返回当前服务端的http版本
URL重定向
URL重定向,也称为URL转发,是一种当实际资源,如单个页面、表单或者整个Web应用被迁移到新的URL下的时候,保持(原有)链接可用的技术。
重定向方法
共有三种重定向的方法:
- http重定向: 通过http redirect实现重定向,具体重定向的code见上文[http状态码详解]
- HTML重定向机制:针对这些特定的应用情景,Web 开发者可以在精心制作的 HTML 页面的 部分添加一个 元素,并将其 http-equiv 属性的值设置为 refresh 。当显示页面的时候,浏览器会检测该元素,然后跳转到指定的页面
# content 属性的值开头是一个数字,指示浏览器在等待该数字表示的秒数之后再进行跳转
<head>
<meta http-equiv="refresh" content="0;URL=http://www.example.com/" />
</head>
- javascript重定向:在 JavaScript 中,重定向机制的原理是设置 window.location 的属性值,然后加载新的页面
window.location = "http://www.example.com/"
优先级
- HTTP 协议的重定向机制永远最先触发
- HTML 的重定向机制 () 会在 HTTP 协议重定向机制未设置的情况下触发
- JavaScript 的重定向机制总是作为最后诉诸的手段,并且只有在客户端开启了 JavaScript 的情况下才起作用
- 任何情况下,只要有可能,就应该采用 HTTP 协议的重定向机制,而不要使用 标签。假如开发人员修改了 HTTP 重定向映射而忘记修改 HTML 页面的重定向映射,那么二者就会不一致,最终结果或者出现无限循环,或者导致其他噩梦的发生
首部字段
End to end header 和Hop to hop header
- End to end header(端到端)
此类别中的首部会转发给请求/响应对应的最终接收目标,且必须保存在由缓存生成的响应中,另外规定它必须被转发
- Hop by hop header(逐跳首部)
此类别中的首部只对单次转发有效,会因通过缓存或代理而不再转发
HTTP/1.1 和之后的版本中,如果要使用逐跳首部,需要提供 Connection 首部字段
主要包括如下字段:Connection Keep-Alive Proxy-Authenticate Proxy-Authorization Trailer TE Transfer-Encoding Upgrade
通用首部字段
通用首部字段是指请求报文和响应报文都会使用的字段
- Cache-Control
Cache-Control下面有很多字段,以逗号分割,其中有一些是服务端的响应信息,有一些是客户端的请求头信息
- 服务端:
# 这里声明的是一个相对的秒数,表示从现在起的3600秒内缓存都是有效的,这样就避免了服务端和客户端时间不一致的问题
# http1.1以后才有
# 当Expires和Cache—Control同时存在时,优先选择Cache-Control
Cache-Control: max-age=3600
# 服务端返回no-cache响应,表示告诉浏览器使用缓存前必须先确认其有效性
Cache-Control: no-cache
# 禁止浏览器或者缓存服务器缓存任何返回响应
Cache-Control: no-store
# 即使它有关联的HTTP身份验证,甚至响应状态代码通常无法缓存的情况也可以缓存响应
# 大多数情况下,“public”不是必需的,因为明确的缓存信息(例如“max-age”)已表示响应是可以缓存的
Cache-Control: public
# 这些响应通常只为单个用户缓存
Cache-Control: private
# 告诉浏览器、缓存服务器,本地副本过期前,可以使用本地副本,本地副本一旦过期,必须去源服务器进行有效性校验,该字段会忽略max-stale字段
Cache-Control: must-revalidate
# 表示所有代理缓存服务器必须向源服务器验证缓存的有效性
Cache-Control: proxy-revalidate
# 代理服务器不可以改变响应主体的媒体类型,防止被压缩
Cache-Control: no-transform
- 客户端
# no-cache表示每次必须向服务端发送请求,但是可以设置If-Modified-Since或者If-None-Match来判断资源有没有过期
# 主要用于验证浏览器本地缓存有没有过期
Cache-Control: no-cache
# 禁止缓存
Cache-Control: no-store
# 要求缓存服务器至少返回未过指定时间的缓存资源
Cache-Control: min-fresh = 60
# 在max-stale指定的时间段内,缓存资源即使过期也照样接收
Cache-Control: max-stale = 3600
# 该头域表示不进行与网络相关的交互,只返回已经缓存且满足要求的数据,如果不满足的话就返回504错误
Cache-Control: only-if-cached
# 代理服务器不可以改变请求主体的媒体类型,防止被压缩
Cache-Control: no-transform
- Connection
# 任何逐段传输头(hop-by-hop)都需要在Connection头中列出,这样代理服务器才不会转发这些头
Connection Upgrade
# 持久连接,http1.0之前默认是非持久连接,http1.1之后默认都是持久连接
Connection KeepAlive
# 强制关闭持久连接
Connection Close
- Date
# HTTP报文的创建时间
Date: Thu, 14 Jun 2018 01:26:07 GMT
- Pragram
# 作为http1.0向后兼容而使用,与cache-Control:no-cache含义一致
Pragram:no-cache
- Trailer
# 事先说明在报文主体后记录了哪些字段,主要用于http1.1的分块传输编码时使用
# 因为数据分块传输,有些header字段只有在数据传输完以后才能知道是什么值
Transfer-Encoding: chunked
Trailer: Expires
- Transfer-Encoding
# 规定了报文传输过程中采用的编码方式,http1.1中只有分块(chunked)编码方式
Transfer-Encoding: chunked
Connection: keep-alive
Content-Encoding: gzip
- Upgrade
# Upgrade用于检查http协议或者其它协议是否可以用更高的版本进行通信
# 客户端
Connection: Upgrade
Upgrade: TLS/1.0
# 服务端
HTTP/1.1 101 Switching Protocols # 如果服务端同意,直接返回101code表切换协议
Connection: upgrade
Upgrade: TLS/1.0
- Via
# Via是为了追踪客户端到服务端的请求和响应报文的传输路径
# 每次经过代理服务器时,都需要将将自己的服务信息添加到Via首部再转发
- Warning
# Warning首部通常告诉用户一些与缓存相关问题的警告
服务端响应首部字段
- Expires
# http1.0和http1.1都支持,表示在此日期之前,客户端都会认为缓存是有效的,第二次请求,浏览器不会连接服务器,直接从本地缓存中读取
# 不过Expires有缺点,比如说,服务端和客户端的时间设置可能不同,这就会使缓存的失效可能并不能精确的按服务器的预期进行
Expires: Thu, 10 Dec 2015 23:21:37 GMT
- Last-Modified
# 服务端返回此文件在服务端的最后修改时间,与下文中讲的客户端的请求头If-Modified-Since是一对
Last-Modified: Mon, 30 Nov 2015 23:21:37 GMT
- ETag
# 协议规格说明定义ETag为“被请求变量的实体值”,是请求文件的一个唯一性标识,与下文中讲的客户端的请求头If-None-Match是一对
ETag: "d41d8cd98f00b204e9800998ecf8427e"
- Accept-Ranges
# Accept-Ranges响应的 HTTP 标头是由服务器使用以通告其支持部分请求的标志物。此字段的值表示可用于定义范围的单位
Accept-Ranges: bytes # 支持范围请求的单位是bytes
Accept-Ranges: none # 不支持范围请求
- Age
# 表示资源在缓存服务器被创建到现在经过了多少时间(s)
Age: 10000
- Location
# 告知客户端服务端提供重定向的URL
# 基本上所有的浏览器接收到Location字段时,都会尝试重定向到指定URL
Location: https://youdata.netease.com
- Proxy-Authenticate
# 将代理服务器所要求的认证信息发送给客户端
Proxy-Authenticate: Basic realm="Access to the internal site"
- WWW-Authenticate
# 将服务端所要求的认证信息发送给客户端
WWW-Authenticate: Basic realm="Access to the internal site"
- Retry-After
# 用于告知客户端多久后再来重试
Retry-After: 120
- Server
# 用于告知当前服务器上安装的http服务软件信息
Server: Apache/2.4.1 (Unix)
- Vary
# 用于告知客户端和代理服务器,在使用缓存时根据request-header中什么字段进行区分
Vary: User-Agent # 表示不同的用户使用不同的缓存
Vary: Accept-Language # 表示不同的语言使用不同的缓存
客户端请求首部字段
- Accept
# 告诉服务器用户代理可以处理的媒体类型,一次可以指定多个媒体类型,并且可以指定优先级
# 用q来表示权重值,用分号隔开,权重值范围时0-1,默认为1
# 下面表示text/plain的权重值为0.3,text/html为1.0
Accept: text/plain; q=0.3, text/html
- Accept-Charset
# 告诉服务器用户代理可以支持的字符集,一次可以指定多个字符集,并且可以指定优先级
Accept-Charset: utf-8, iso-8859-1;q=0.5
- Accept-Encoding
# 告诉服务器用户代理可以支持的内容编码方式,一次可以指定多个内容编码方式,并且可以指定优先级
Accept-Encoding: gzip,deflate,br
# gzip压缩算法:一般经过 gzip 压缩过的文本响应,只有原始大小的 1/4
# deflate压缩算法:也是一种使用 DEFLATE 的压缩格式
# br压缩算法:与常见的通用压缩算法不同,Brotli使用一个预定义的120千字节字典。该字典包含超过13000个常用单词、短语和其他子字符串,这些来自一个文本和HTML文档的大型语料库。
预定义的算法可以提升较小文件的压缩密度,使用Brotli替换Deflate来对文本文件压缩通常可以增加20%的压缩密度,而压缩与解压缩速度则大致不变
- Accept-Language
# 用户代理可以处理的自然语言集,可以接收多个语言,并指定优先级
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
- Authorization
# 服务器可以用来针对客户端的请求发送challenge(质询信息),客户端则可以用Authorization来提供身份验证凭证。流程如下:
# 1. 服务器端向客户端返回 401(Unauthorized,未被授权的)状态码,并在WWW-Authenticate首部提供如何进行验证的信息,其中至少包含有一种质询方式。
# 2. 之后有意向证明自己身份的客户端可以在新的请求中添加Authorization首部字段进行验证,字段值为身份验证凭证信息。
# 3. 通常客户端会弹出一个密码框让用户填写,然后发送包含有恰当的Authorization首部的请求
# 4. 通常在Basic认证中,会将用户和密码部分组合成:"username"+":"+"password"的形式,然后进行Base64编码
Authorization: Basic dXNlcjpwYXNz
- Proxy-Authorization
# Proxy-Authorization与Authorization的作用相同,不同之处是,前者用于客户端与代理服务器之间的认证,后者用于客户端与服务端之间的认证
Proxy-Authorization: Basic dXNlcjpwYXNz
- Expect
# 是一个请求消息头,包含一个期望条件,表示服务器只有在满足此期望条件的情况下才能妥善地处理请求
# 通知接收方客户端要发送一个体积可能很大的消息体,期望收到状态码为100 (Continue) 的临时回复
Content-Length: 1234567890987
Expect: 100-continue
- From
# 请求首部From中包含一个电子邮箱地址,这个电子邮箱地址属于发送请求的用户代理的实际掌控者的人类用户
# 这个用于服务器在遇到问题时,可以及时联系到代理服务器或者客户端
From: webmaster@example.org
- Host
# Host用于标志主机名和端口号,是HTTP1.1中规定的唯一被必须包含的字段
Host www.baidu.com
- If-Modified-Since
# 浏览器每次请求会将客户端上次返回的Last-Modified当作If-Modified-Since报头发送给服务端
# 服务端判断在该时间之后文件有没有被修改,如果修改了则返回新的资源,否则返回 HTTP 304 (Not Changed)状态码,内容为空
If-Modified-Since: Mon, 30 Nov 2015 23:21:37 GMT
- If-Unmodified-Since
# If-Unmodified-Since与If-Modified-Since作用刚好相反,浏览器每次请求会将客户端上次返回的Last-Modified当作If-Unmodified-Since报头发送给服务端
# 服务端判断在该时间之后文件有没有被修改,如果没有修改则处理请求,否则返回状态码412表示PreCondition Failed
If-Unmodified-Since: Mon, 30 Nov 2015 23:21:37 GMT
- If-None-Match
# 浏览器每次请求会将客户端上次返回的ETag当作If-None-Match报头发送给服务端
# 服务端判断在ETag有没有变化,如果修改了则返回新的资源,否则返回 HTTP 304 (Not Changed)状态码,内容为空
If-None-Match: W/"d41d8cd98f00b204e9800998ecf8427e"
- If-Match
# If-Match和If-None—Match的作用刚好相反
# 只有当客户端发送的If-Match与服务端生成的ETag信息相等时,才处理请求,否则返回状态码412表示PreCondition Failed
If-Match: W/"d41d8cd98f00b204e9800998ecf8427e"
- If-Range
# If-Range字段值若是和ETag值或者更新的日期时间指一致,则作为范围请求处理,否则忽略范围请求返回全部资源
If-Range: "123456"
Range: bytes=5001-10000
- Max-Forwords
# Max-Forwords表示可经过服务器的最大个数,每次在向下一个服务器发送请求之前,数值减1
# 用于TRACE和OPTIONS方法中,可以检查服务器状况进行问题排查
Max-Forwords: 10
- Range
# 获取资源部分范围的请求
# 如果成功处理该范围的请求则返回206Partial Content的响应,否则返回200code及全部资源
Range: 5000-10000
- Referer
# 告知服务器请求的资源的原始URI
Referer: https://youdata.netease.com/dash/folder/1
- TE
# TE用于告知服务端,客户端可以接收的传输编码方式以及相对的优先级
TE: gzip, deflate;q=0.5
- User-Agent
# 会将创建请求的浏览器及用户代理名称等信息传递给服务端
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36
实体首部字段
- ALLOW
# 服务端用于告知客户端支持的请求方式
# 如果服务端接收到不支持的请求方式,会以405(Method Not Allowed)返回
ALLOW: GET, POST, HEAD
- Content-Encoding
# 用于告知客户端,服务器对主体部分采用什么压缩算法进行压缩
Content-Encoding: gzip
- Content-Language
# 用于告知客户端,服务器对主体部分采用什么自然语言
Content-Language: zh-CN
- Content-Length
# 表明请求主体的大小
# 如果对传输实体进行编码传输时,不能使用Content-Length
Content-Length: 10000
- Content-Location
# Content-Location 首部指定的是要返回的数据的地址选项。最主要的用途是用来指定要访问的资源经过内容协商后的结果的URL。
# Location 与 Content-Location是不同的,前者(Location )指定的是一个重定向请求的目的地址(或者新创建的文件的URL),而后者( Content-Location) 指向的是可供访问的资源的直接地址,不需要进行进一步的内容协商。
# Location 对应的是响应,而Content-Location对应的是要返回的实体
Content-Location: /index.html
- Content-MD5
# Content-MD5 的值是服务端对报文主体进行MD5计算再经过base64编码生成的。
# 客户端收到数据以后,同时可以对报文进行MD5计算再经过base64编码对比结果是否一致,来验证数据的是否正确
Content-MD5: djkljalksjdlkjklsjdkljskdljkldfjkljlds
- Content-Range
# 针对范围请求,返回对应范围的数据
Content-Range: 5001-10000
- Content-Type
# 说明实体对象的媒体类型
Content-Type: application/json; charset=utf-8
- Expires
# 源服务器用于告知缓存服务器或者客户端,该响应实体最长可以缓存到什么时候
Expires: Wed, 21 Oct 2015 07:28:00 GMT
- Last-Modified
# 指明资源最后一次被修改的时间
Last-Modified: Wed, 21 Oct 2015 07:28:00 GMT
- Set-Cookie
# 服务端设置cookie信息并告知客户端
Set-Cookie: SESSION_YOUDATA=mzXPyXr2qCImHDOuIl60ba57; path=/; expires=Mon, 09 Jul 2018 07:48:51 GMT; secure; httponly
- Cookie
# 客户端将自己保存的cookie设置发送给服务端
Cookie: SESSION_YOUDATA=mzXPyXr2qCImHDOuIl60ba57
参考文献
- HTTP 请求头中的 X-Forwarded-For
- JavaScript中伪协议 javascript:使用探讨
- HTTP 301 和 302 跳转的本质区别?
- 使用nginx后如何在web应用中获取用户ip及原理解释
- 关于片段URL你应该知道的6个要点
- 细说 Data URI
- PUT 还是 POST ? 【已翻译100%】
- 常见的HTTP Method深度解析
- 语言编辑高级HTTP的重定向
- HTTP Status Codes
- 浏览器缓存 Last-Modified / Etag / Expires / Cache-Control 详解
- HTTP 缓存
- 使用 HTTP 缓存:Etag, Last-Modified 与 Cache-Control
- HTTP 协议中的 Transfer-Encoding
- 把Gzip换成Brotli的Nginx配置教程
- 使用Brotli提高网站访问速度