You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP网页代理重定向逻辑问题:跳转路径异常修正求助

解决PHP网页代理的重定向跳转问题

你的问题核心在于:代码开启了curl的自动跟随重定向,并且直接转发目标服务器的Location响应头,导致浏览器直接跳转到目标站点的路径,而非通过代理的?url=参数跳转。

解决步骤:

  1. 关闭curl自动跟随重定向:让curl返回原始的重定向响应,而非直接跳转后的内容,方便手动处理Location头。
  2. 拦截重定向状态码:识别3xx系列HTTP状态码(301、302、303、307、308),提取目标跳转地址。
  3. 转换跳转地址为代理格式:若目标地址是相对路径,先拼接成完整URL;若是绝对URL则直接使用,再构造代理跳转路径/?url=完整跳转URL。
  4. 替换响应头:用构造好的代理跳转地址替换原服务器的Location头后发送给浏览器。

修改后的完整代码:

<?php
if (!isset($_GET['url'])) {
    header('HTTP/1.1 400 Bad Request');
    echo 'Missing URL parameter';
    exit;
}

$url = $_GET['url'];

if (!filter_var($url, FILTER_VALIDATE_URL)) {
    header('HTTP/1.1 400 Bad Request');
    echo 'Invalid URL';
    exit;
}

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// 关闭自动跟随重定向,手动处理跳转
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);

$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$content_type = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
$content_length = curl_getinfo($ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD);
// 获取当前请求的有效URL,用于拼接相对路径
$effective_url = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);

curl_close($ch);

// 处理重定向状态码
$redirect_codes = [301, 302, 303, 307, 308];
if (in_array($http_code, $redirect_codes)) {
    // 提取Location头内容
    preg_match('/Location: (.*)\r\n/', $response, $matches);
    if (!empty($matches[1])) {
        $target_location = trim($matches[1]);
        // 处理相对路径,转换为绝对URL
        if (!filter_var($target_location, FILTER_VALIDATE_URL)) {
            $parsed_effective = parse_url($effective_url);
            $base_url = $parsed_effective['scheme'] . '://' . $parsed_effective['host'];
            if (!empty($parsed_effective['port'])) {
                $base_url .= ':' . $parsed_effective['port'];
            }
            // 拼接相对路径
            if (str_starts_with($target_location, '/')) {
                $target_location = $base_url . $target_location;
            } else {
                $current_path = dirname($parsed_effective['path']);
                $target_location = $base_url . $current_path . '/' . $target_location;
            }
        }
        // 构造代理跳转地址
        $proxy_redirect = '/?url=' . urlencode($target_location);
        // 发送重定向响应头
        header('HTTP/1.1 ' . $http_code);
        header('Location: ' . $proxy_redirect);
        exit;
    }
}

if ($http_code !== 200) {
    header('HTTP/1.1 ' . $http_code);
    echo 'Failed to fetch the content';
    exit;
}

$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$headers = substr($response, 0, $header_size);
$body = substr($response, $header_size);

// 转发响应头时跳过Location(已处理)和不需要的头
foreach (explode("\r\n", $headers) as $header) {
    if (!empty($header) && stripos($header, 'Content-Length') === false 
        && stripos($header, 'Transfer-Encoding') === false
        && stripos($header, 'Location') === false) {
        header($header);
    }
}

header('Content-Type: ' . $content_type);

if ($content_length > 0) {
    header('Content-Length: ' . $content_length);
}

// (可选)处理响应体中的相对链接,比如a标签、img标签的路径
// 示例:$body = preg_replace('/href="([^"]+)"/', 'href="/?url=' . urlencode($base_url) . '/$1"', $body);

echo $body;
?>

额外说明:

  • 代码中新增了相对路径跳转的处理逻辑,确保目标服务器返回相对路径时,能正确转换为完整URL再构造代理地址。
  • 若需要页面内所有链接(如<a>、<img>)都通过代理访问,可参考代码中的注释添加正则替换逻辑,将相对路径转换为代理格式的URL。

内容的提问来源于stack exchange,提问作者Kaj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 14:57:02