写了一个简单的PHP反向代理
用PHP写了个简单的反代
特性
- 直接输入域名即可访问, 例如
httpbin.org/get - 替换页面内的 URL, 例如
http://example.com/login => http://~/proxy/http://example.com/login - 支持 GET 和 POST 请求
已知 Bug
- 无法识别重定向
- 无法携带
Cookies - 不支持相对 URL 替换, 例如
/blog/1和./features - 不支持前端路由
- 不支持动态页面跳转, 例如
window.location.href = "/blog/" + ${blogId}
源码
已在 Github 开源
<?php
/**
* PHP Reverse Proxy
* By shikukuya
*/
error_reporting(0); // 关闭第一次请求出错时的警告
$url_pattern = "/https?:\/\/[-A-Za-z0-9+&@#\/%?=~_|!:,.;]+[-A-Za-z0-9+&@#\/%=~_|]/"; // 用于匹配页面内的URL
$real_url = $_SERVER["QUERY_STRING"]; // 真实的URL在问号(?)后
$server_name = $_SERVER["SERVER_NAME"]; // 服务器域名端口
$method = $_SERVER["REQUEST_METHOD"]; // 请求方法
$headers = getallheaders(); // Apache独有方法,获取请求头
$headers_string = ""; // 用于存放字符串格式请求头
foreach ($headers as $k => $v) { // 将键值对转为字符串
$headers_string = "$headers_string$k: $v\n";
}
if (!preg_match($url_pattern, $real_url)) { // 如果只输入了域名
$real_url = "http://$real_url"; // 添加“http://”
}
request: // 标签,重试时跳转到这里
$options["http"] = [
"timeout" => 15, // 超时时间
"method" => $method, // 请求方法
"header" => $headers_string, // 请求头
];
$context = stream_context_create($options);
$response = file_get_contents($real_url, false, $context); // 发送请求
if ($response) { // 成功了
$response = preg_replace_callback($url_pattern, function ($m) {
global $server_name;
return "http://$server_name/proxy/?" . $m[0];
}, $response); // 替换页面内的URL
header("Content-Type: " . $http_response_header["Content-Type"]); // 修改Content-Type
echo $response; // 输出
} else { // 失败了
if ($headers_string === "") { // 已经重试过了
die("无法访问此页面");
} else { // 还没有重试
$headers_string = ""; // 清楚请求头重试
goto request;
}
}

浙公网安备 33010602011771号