PHP 怎么PHP 反向代理

wen PHP项目 2

本文目录导读:

PHP 怎么PHP 反向代理

  1. 场景一:纯 PHP 实现反向代理(适合小流量或特殊业务)
  2. 场景二:使用 Web 服务器反向代理(推荐生产环境)
  3. 使用 PHP 第三方库实现代理

在 PHP 中实现反向代理,通常有两种场景:

  1. 作为应用层代理:PHP 脚本接收请求后,通过 cURLfile_get_contents 向目标服务器发起新的请求,再返回结果。
  2. 利用 Web 服务器功能:通过 Nginx 或 Apache 配置反向代理,PHP 本身不参与代理逻辑(性能最佳)。

下面分别说明两种实现方式,重点聚焦 PHP 代码实现反向代理


纯 PHP 实现反向代理(适合小流量或特殊业务)

PHP 作为代理服务器,接收所有请求后转发给后端目标服务器。

基础示例(仅代理 GET 请求)

<?php
$targetUrl = 'http://192.168.1.100:8080'; // 目标服务器地址
// 获取当前请求的路径和查询参数
$path = $_SERVER['REQUEST_URI'];
$finalUrl = $targetUrl . $path;
// 初始化 cURL
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $finalUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, false);
// 转发请求头(可选)
$headers = getallheaders();
$curlHeaders = [];
foreach ($headers as $key => $value) {
    $curlHeaders[] = "$key: $value";
}
curl_setopt($ch, CURLOPT_HTTPHEADER, $curlHeaders);
// 执行请求
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// 设置响应状态码
http_response_code($httpCode);
// 设置 Content-Type(若有)
// 这里简单范例不做解析,实际可以获取目标响应的 header
// 输出结果
echo $response;

完整的代理函数(支持 GET/POST/PUT/DELETE、请求体、自定义头)

<?php
function reverseProxy($targetBaseUrl) {
    $url = $targetBaseUrl . $_SERVER['REQUEST_URI'];
    $method = $_SERVER['REQUEST_METHOD'];
    // 获取请求体
    $body = file_get_contents('php://input');
    // 获取客户端请求头
    $headers = getallheaders();
    $curlHeaders = [];
    foreach ($headers as $key => $value) {
        // 可过滤掉一些不宜转发的头(如 Host, Connection)
        if (strtolower($key) !== 'host' && strtolower($key) !== 'connection') {
            $curlHeaders[] = "$key: $value";
        }
    }
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $curlHeaders);
    // 有请求体时发送
    if ($body) {
        curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
    }
    // 获取响应头(如果需要转发响应头给客户端)
    curl_setopt($ch, CURLOPT_HEADER, true);
    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    // 分离响应头和响应体
    $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
    $responseHeader = substr($response, 0, $headerSize);
    $responseBody = substr($response, $headerSize);
    curl_close($ch);
    // 设置 HTTP 状态码
    http_response_code($httpCode);
    // 转发响应头(可选)
    $headerLines = explode("\r\n", $responseHeader);
    foreach ($headerLines as $line) {
        if (stripos($line, 'Transfer-Encoding') === false && 
            stripos($line, 'Connection') === false) {
            header($line, false);
        }
    }
    echo $responseBody;
}
// 使用
reverseProxy('http://backend-server:8080');

注意事项

  • 纯 PHP 代理性能较差,每次请求都会消耗 PHP 进程来处理转发,不适合高并发。
  • 需要处理 cookie、SSL、超时、连接池等问题。
  • 建议配合 Web 服务器(如 Nginx 转发到 PHP-FPM)使用,而非直接监听外部端口。

使用 Web 服务器反向代理(推荐生产环境)

Nginx 配置示例

server {
    listen 80;
    server_name example.com;
    location / {
        proxy_pass http://127.0.0.1:8080; # 后端服务地址
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Apache 配置示例(需启用 mod_proxy)

<VirtualHost *:80>
    ServerName example.com
    ProxyPreserveHost On
    ProxyPass / http://127.0.0.1:8080/
    ProxyPassReverse / http://127.0.0.1:8080/
</VirtualHost>

PHP 在这种情况下无需任何代理代码,只负责处理业务逻辑。


使用 PHP 第三方库实现代理

如果非要纯 PHP 且想减少代码量,可使用 guzzlehttp/guzzle 配合中间件:
但最终原理仍是 cURL,只是封装了更多功能。

composer require guzzlehttp/guzzle
<?php
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\Request;
require 'vendor/autoload.php';
$client = new Client(['base_uri' => 'http://target-server/']);
$request = new Request($_SERVER['REQUEST_METHOD'], $_SERVER['REQUEST_URI']);
$response = $client->send($request);
// 转发状态码和响应
http_response_code($response->getStatusCode());
echo $response->getBody();

方式 适用场景 性能 复杂度
Web服务器反向代理 (Nginx/Apache) 生产环境、高并发 极高 低(只需配置)
PHP cURL 代码代理 小流量、特殊业务(如需修改请求/响应)
PHP 框架/库代理 快速开发,已有 Guzzle 环境

建议

  • 大部分情况下使用 Nginx 反向代理
  • 只有当需要动态修改请求或响应内容、或无法修改 Web 服务器配置时,才考虑 PHP 代码实现代理。

如果需要在 PHP 中实现更完整的代理(支持 WebSocket、长连接、负载均衡等),请进一步说明你的具体需求,可以提供更定制化的方案。

抱歉,评论功能暂时关闭!