目录
最近在测试proxy_guess的图片302跳转,由于需要标记请求,所以我在请求时同时记录了端口。而有时就发现,haeder中打印的端口居然和后续获取的端口不一致。为此,我做了些测试。并发现了些奇葩的事情。
乌龙
好吧,这是一个乌龙事件。我发现了这个奇怪现象的前提:
chrome打开了devtool,并保持在【网络】的选项卡
原因是:在加载这种302带跳转的图片时,devtool显示缩略图时会再加载一遍。
测试代码
测试浏览器为:
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36
php部分
<?php
if(empty($_GET['token'])){
$_GET['token'] = rand(0,999999);
}
function wlog($text){
$path_file = __DIR__.'/'.'one_request.log';
file_put_contents($path_file,date('Y-m-d H:i:s').' '. (is_array($text)?json_encode($text):$text)."\n", FILE_APPEND);
};
$params = [
'token'=>$_GET['token'],
'p'=>$_SERVER['REMOTE_PORT'],
'protocol'=>$_SERVER['SERVER_PROTOCOL']
];
if(empty($_GET['p'])){
header('port:'.$_SERVER['REMOTE_PORT']);
header('Location: index.php?'.http_build_query($params));
wlog($params);
exit;
}else{
header('port:'.$_SERVER['REMOTE_PORT']);
wlog($params);
header('content-type:image/png');
echo base64_decode('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAADElEQVQI12NgYGAAAAAEAAEnNCcKAAAAAElFTkSuQmCC');
exit;
}
img tag
let image = new Image();
let token = Math.random()
image.onload = function(){
}
image.src = "index.php?token="+token;
nginx 部分
……
listen 443 ssl ;// http/1.1
……
通过 http2 选项和 keepalive_timeout 可以搭配出4个组合。
protocol |
keepalive_timeout |
keep-alive client |
H2 |
75 |
y |
H2 |
0 |
x |
http/1.1 |
75 |
y |
http/1.1 |
0 |
x |
测试数据
H2 and enbale keep-alive
browser address bar
2022-10-20 06:35:44 {"token":161829,"p":"15597","protocol":"HTTP\/2.0"}
2022-10-20 06:35:44 {"token":"161829","p":"15597","protocol":"HTTP\/2.0"}
- 链接id如图
img tag
2022-10-20 06:36:28 {"token":"0.5107532597240456","p":"15597","protocol":"HTTP\/2.0"}
2022-10-20 06:36:28 {"token":"0.5107532597240456","p":"15597","protocol":"HTTP\/2.0"}
2022-10-20 06:36:28 {"token":"0.5107532597240456","p":"15635","protocol":"HTTP\/2.0"}
2022-10-20 06:36:28 {"token":"0.5107532597240456","p":"15635","protocol":"HTTP\/2.0"}
- 链接id如图
H2 and disabale keep-alive
browser address bar
2022-10-20 06:40:09 {"token":495172,"p":"15776","protocol":"HTTP\/2.0"}
2022-10-20 06:40:09 {"token":"495172","p":"15777","protocol":"HTTP\/2.0"}
- 链接id如图
img tag
2022-10-20 06:40:49 {"token":"0.8067361045275498","p":"15833","protocol":"HTTP\/2.0"}
2022-10-20 06:40:49 {"token":"0.8067361045275498","p":"15835","protocol":"HTTP\/2.0"}
2022-10-20 06:40:49 {"token":"0.8067361045275498","p":"15834","protocol":"HTTP\/2.0"}
2022-10-20 06:40:49 {"token":"0.8067361045275498","p":"15836","protocol":"HTTP\/2.0"}
- 链接id如图
htpp/1.1 and enbale keep-alive
browser address bar
2022-10-20 06:32:57 {"token":229425,"p":"15473","protocol":"HTTP\/1.1"}
2022-10-20 06:32:58 {"token":"229425","p":"15473","protocol":"HTTP\/1.1"}
- 链接id如图
img tag
2022-10-20 06:23:50 {"token":"0.6276816635368629","p":"14825","protocol":"HTTP\/1.1"}
2022-10-20 06:23:50 {"token":"0.6276816635368629","p":"14825","protocol":"HTTP\/1.1"}
2022-10-20 06:23:50 {"token":"0.6276816635368629","p":"14826","protocol":"HTTP\/1.1"}
2022-10-20 06:23:50 {"token":"0.6276816635368629","p":"14826","protocol":"HTTP\/1.1"}
- 链接id如图
htpp/1.1 and disabale keep-alive
browser address bar
2022-10-20 06:31:21 {"token":293483,"p":"15387","protocol":"HTTP\/1.1"}
2022-10-20 06:31:21 {"token":"293483","p":"15388","protocol":"HTTP\/1.1"}
img tag
2022-10-20 06:29:48 {"token":"0.5968497764216198","p":"15284","protocol":"HTTP\/1.1"}
2022-10-20 06:29:48 {"token":"0.5968497764216198","p":"15285","protocol":"HTTP\/1.1"}
2022-10-20 06:29:48 {"token":"0.5968497764216198","p":"15286","protocol":"HTTP\/1.1"}
2022-10-20 06:29:48 {"token":"0.5968497764216198","p":"15287","protocol":"HTTP\/1.1"}
- 链接id如图
所以呢?奇葩在哪?
首先说些正常的
- 会话保持开启时,无论通过地址栏还是通过图片访问,H2和http/1.1都会复用原来的请求,使用一个端口。
- 会话保持关闭时,无论通过地址栏还是通过图片访问,H2和http/1.1都会重新打开一个端口。
奇葩的地方
- 通过图片访问,居然会触发4个请求,比通过地址栏访问的多出2个!
- 在H2开启会话保持的时候,通过图片访问,多出来的请求没有复用原来的端口,而是重启打开了一个端口
- 在HTTP/1.1 关闭会话保持时,通过图片(带302跳转)访问时,居然可以开启4个端口
总结
一个302跳转图片+关闭会话保持,我猜应该不会有人这么干吧。
- 如果你刚刚好有使用一个302跳转的图片标签做统计或者触发任务,那么你需要考虑重复触发的问题了
- 会话保持开启 + 302跳转的图片可以在保持性能的情况下让客户端发起额外的一次握手
- 如果你有端口检测服务,可以考虑 HTTP/1.1 + 会话保持关闭 + 302 图片跳转,当然我想不出这有什么用
- 1一个请求4个端口触发12次TCP握手+28次TSL握手……,太残忍了,请避免这么做
- 该问题的原因未知,并且是否所有浏览器都会有该现象,还需要更多测试。
补充
- 图片不做302跳转是不会出现以上情况。
- H2 开启会话保持的情况下,额外的端口在下次额外的请求中会被复用。