第一个请求http://example.com:
GET / HTTP/1.1
Host: example.com
Connection: close
User-Agent: Paw/2.3.3 (Macintosh; OS X/10.11.4) GCDHTTPRequest
此时,DNS通过302将请求转发到https://www.example.com.(注意协议更改)
HTTP/1.1 302 Found
Location: https://www.example.com
此时Paw发出以下请求(此时为https):
GET / HTTP/1.1
Host: www.example.com
得到这样的回应:
HTTP/1.1 302 Found
Server: Cowboy
Connection: close
X-Powered-By: Express
X-Frame-Options: SAMEORIGIN
Location: /verify-age
这就是事情变得有趣的地方。没有主机名信息的Location实际上会向原始主机名和协议发出下一个请求!!(现在返回http请求?!):
GET /verify-age HTTP/1.1
Host: example.com
它被DNS服务器拦截,DNS服务器当然会回复302:
HTTP/1.1 302 Found
Location: https://www.example.com
回到正确的协议和url,但循环当然会回到302重定向到/验证年龄,它会切换回原始协议和主机名!我们陷入了这个循环。奇怪的是,Chrome没有遵循这个循环,但Paw遵循了。那么谁在这里不好呢?DNS?爪子节点?铬?
这很有趣。虽然RFC2616要求Location
报头字段值由单个绝对URI(Location = "Location" ":" absoluteURI
)组成,但在RFC7231中对此进行了修改,放宽了原始约束,允许使用相对URL(Location = URI-reference
),引用RFC3986进行位置值计算。
在第5.1节RFC3986中明确指出:
注意,如果检索是重定向请求的结果,最后使用的URI(即,导致实际检索的URI表示的)是基本URI。
所以我的猜测是,对原始主机名发出下一个请求的浏览器在这里是错误的。
更新:此错误已在Paw 2.3.4 中修复
我确认这是Paw的一个bug,我已经能够自己复制它了。我们将在Paw的下一个错误修复版本中解决这个问题,该版本有望在10天内发布。感谢您的报道,并对给您带来的不便表示歉意。