为什么HTTP请求行中会出现“https”?

问题

HTTP明明是跑在TLS之上,怎么会意识到https的存在呢?

太长不看

在HTTP/1.1给正向代理的请求行中,方法后面的参数是 absoluteURI,而非 http URL,即可以使用任何代理支持的协议。 也就是说,该参数表达的是任何可以识别特定资源的标志,所以https作为一种协议可能会出现在该位置。

文档规定

RFC2616 中,规定请求行的格式为 Method SP **Request-URI** SP HTTP-Version CRLF,而 Request-URI 的格式为 "*" | absoluteURI | abs_path | authority。其中,abs_path 是我们最常看到的,例如 /pub/WWW/TheProject.html,通过联合请求头中的HOST字段,我们就可以访问到资源了。

但有时我们的HTTP请求是给一个正向代理的。HTTP/1.1规定,在这种情况下,Request-URI 必须 absoluteURI 的格式,即 scheme ":" ( hier_part | opaque_part ) 。其中,scheme 定义了该URI的命名空间,告诉了代理该资源标识符的语义和语法。所以,它可以是 https:// … 或者 ftp:// … ,甚至可以不指定协议,例如 file:// …

同时,为了避免在代理的过程中产生回环, RFC2616 要求代理的实现必须能够通过 absoluteURI 确定资源所有的服务器/别名,IP地址,主机名等。

设计分析

为什么给正向代理的HTTP请求行中需要URI,而非 abs_path + HOST字段?

因为这里只确定客户端和代理之间是通过HTTP协议通信的,并不知道代理会通过何种方式访问资源。所以我们需要在HTTP请求行中告知代理URI,如果代理支持对应的访问,则在成功获取资源后通过HTTP返回给客户端。

另外,除了直接请求资源服务器,代理也可能把这个请求交给下一个代理,这之间的通信也可能不是基于HTTP的,只有代理在知道完整URI的情况下才能确保接下来的步骤正确运行。

如果使用绝对URI,是否会和HOST字段的信息产生冗余?

在HTTP/1.1中,HOST字段是强制的。其目的是告知服务端请求资源所在的(虚拟)主机和端口号,例如 Host: www.w3.org所以代理请求行中的绝对URI是会和HOST产生信息冗余的。事实上,RFC7230 规定这种情况下代理必须忽略HOST字段信息,并通过请求行中的URI重新填充HOST字段。

为什么实现不良的代理可能会产生回环?

在现在的网络环境下,CDN/反向代理的情况非常普遍。CDN的边际网络会根据请求选择直接返回缓存或者继续转发请求,所以一个请求可能会被多次代理。但是,如果代理无法、或错误的判断资源来源时,就可能发生回环。例如,代理 A 判断应该把请求交给代理B,但是 B 在接到请求后认为该请求应该交给代理 A ,这样就形成了回环(也可能有多个节点),最终导致请求被丢弃。

如上图所示,这种回环的发生不仅导致了数据的丢失,也耗费了大量带宽和代理的资源。事实上,这也被作为一种对CDN的“杠杆”拒绝服务攻击

关于如何通过扩展HTTP头来解决这个问题,可以参考 Preventing Request Loops Using CDN-Loop

后记

回到最初的问题,如上所述,代理对于不同 scheme 的支持完全取决于实现,如果代理无法支持以 https:// 开头的代理请求,则会返回4xx状态。例如 CDN 提供商 fastly 在4年前就是这样

原文地址:https://www.cnblogs.com/liqiuhao/p/12204084.html

时间: 2024-10-12 20:02:56

为什么HTTP请求行中会出现“https”?的相关文章

请求行与相应行

请求行 常见方法(RFC7231) 用于文档管理的WEBDAV 方法(RFC2518) HTTP响应行 其中,HTTP/1.1表示协议版本:200表示状态码:OK是状态说明. 2.状态码 根据响应结果的类型,大致分为以下几类: 2.1 1XX(信息类) 请求已接收到,需要进一步处理才能完成,HTTP1.0不支持 该类型状态码表示接收到请求并且继续处理. 100 Continue:客户端必须继续发出请求,上传大文件前使用 由客户端发起请求中携带 Expect:100-continue 头部触发 1

HTTP 请求头中的 X-Forwarded-For

我一直认为,对于从事 Web 前端开发的同学来说,HTTP 协议以及其他常见的网络知识属于必备项.一方面,前端很多工作如 Web 性能优化,大部分规则都跟 HTTP.HTTPS.SPDY 和 TCP 等协议的特点直接对应,如果不从协议本身出发而是一味地照办教条,很可能适得其反.另一方面,随着 Node 的发展壮大,越来越多的前端同学开始写服务端程序,甚至是框架( ThinkJS 就是这样由前端工程师开发,并有着众多前端工程师用户的 Node 框架),掌握必要的网络知识,对于服务端程序安全.部署.

接口测试基础知识详解http请求由三部分组成,分别是:请求行、消息报头、请求正文 1、请求行以一个方法符号开头,以空格分开,后面跟着请求的URI和协议的版本,格式如下:Method Request-URI HTTP-Version CRLF 其中 Method表示请求方法;Request-URI是一个统一资源标识符;HTTP-Version表示请求的HTTP协议版本;CRLF表示回车和换行(除了

HTTP URL (URL是一种特殊类型的URI,包含了用于查找某个资源的足够的信息)的格式如下:http://host[":"port][abs_path]http表示要通过HTTP协议来定位网络资源:host表示合法的Internet主机域名或者IP地址:port指定一个端口号,为空则使用缺省端口80:abs_path指定请求资源的URI:如果URL中没有给出abs_path,那么当它作为请求URI时,必须以"/"的形式给出,通常这个工作浏览器自动帮我们完成.e

HTTP 笔记与总结(2 )HTTP 协议的(请求行的)请求方法 及 (响应行的)状态码

(请求行的)请求方法 包括: GET,POST,HEAD,PUT,TRACE,DELETE,OPTIONS 注意:这些请求方法虽然是 HTTP 协议规定的,但是 Web Server 未必允许或支持这些方法. HEAD 和 GET 基本一致,只是不返回内容,比如只是确认一个内容还正常存在,不需要返回具体内容.演示: GET: HEAD: HEAD 方法只返回了响应的头信息. PUT,往服务器上的资源传输内容: 服务器未必支持 HTTP 协议所规定的方法. TRACE, 例如使用了代理上网(例如访

如何在Linux命令行中创建以及展示演示稿

你在准备一场演讲的时候,脑海可能会先被图文并茂.形象华丽的演示图稿所占据.诚然,没有人会否认一份生动形象的演讲稿所带来的积极作用.然而,并非所有的演讲都需要TED Talk的质量.更多时候,演讲稿只为传达特定的信息. 而这个,使用文本信息足以完成.在这种情况下,你的时间可以更好的花在信息的搜集和核实上面,而不是在谷歌图片搜索(Google Image)上寻找好看的图片. 在Linux的世界里,有几个不同的方式供你选择来做演讲.比如带有大量多媒体展示.视觉冲击效果极佳的Impress.js,专为L

http请求头中的Content-Type属性在angular 和 node中的用法

post请求的请求体有以下两种格式: 1. 字符串: 'name=code_bunny&age=12' 这种格式的请求体,需要配置请求头 'Content-Type':'application/x-www-form-urlencoded' 2. json: {name:'code_bunny',age:12} 这种格式的请求体,需要配置请求头 'Content-Type':'application/json;charset=UTF-8' 注意: 请求体格式和请求头的Content-Type类型必

HTTP请求头中的那些东西

一.HTTP请求头是什么? HTTP请求头,HTTP客户程序(例如浏览器),向服务器发送请求的时候必须指明请求类型(一般是GET或者POST).如有必要,客户程序还可以选择发送其他的请求头. 二.HTTP头中都有什么? 1.请求类型:我们常见的请求类型有Get和Post两种请求,而这个信息在HTTP请求报文中的地一行即请求中就可以得到: 2.请求地址:请求地址告诉服务端当前请求来自哪里,例如"/"表示的是服务器根目录,对一个静态网站而言,如果存在index.html 则指向该网页:对一

HTTP请求方法中中GET和POST的区别(详细描述)

HTTP协议在现代网络通信中被广泛应用,在HTTP 1.0版本中有7种请求方式,在HTTP 1.1版本中有8种请求方式,而这些请求方式中最常用的就是GET和POST,网上关于GET与POST请求方式的区别的文章很多,但却都不够全面.现在我们来全面阐述这两种方法的区别. (一)从HTTP报文来看 GET请求方式将请求信息放在URL后面,请求信息和URL之间以?隔开,请求信息的格式为键值对,例如 https://baike.baidu.com/item/Python/407313?fr=aladdi

mysql中如何在命令行中,执行一个SQL脚本文件?

需求描述: 在mysql数据库的使用中,有的时候,需要直接在shell的命令行中,执行某个SQL脚本文件, 比如,要初始化数据库,创建特定的存储过程,创建表等操作,这里进行一个基本的测试. 一般情况,mysql都是以交互式的方式登录,执行SQL语句的.这里要做的就是将SQL放在一个文件里,让mysql 客户端程序来执行. 操作过程: 1.创建一个SQL脚本的文本文件,里面放想要执行的SQL语句 use test01 select count(*) from ts051; 备注:SQL脚本的文件名