PHP 如何获取原始请求体

wen PHP项目 1

本文目录导读:

PHP 如何获取原始请求体

  1. 使用 php://input 流(最常用)
  2. 使用 $HTTP_RAW_POST_DATA(PHP 5.6 之前)
  3. 使用 php://input 的注意事项
  4. 完整的请求体获取函数
  5. 处理不同 HTTP 方法的请求
  6. 使用 cURL 测试 API
  7. 最佳实践建议

在 PHP 中获取原始请求体有多种方法,以下是主要的几种方式:

使用 php://input 流(最常用)

<?php
// 获取原始请求体
$rawBody = file_get_contents('php://input');
// 如果是 JSON 数据,可以解码
$data = json_decode($rawBody, true);
// 输出原始数据
echo $rawBody;
?>

使用 $HTTP_RAW_POST_DATA(PHP 5.6 之前)

<?php
// 注意:此方法在 PHP 5.6+ 已废弃,PHP 7.0+ 已移除
// 需要在 php.ini 中启用 always_populate_raw_post_data
global $HTTP_RAW_POST_DATA;
$rawBody = $HTTP_RAW_POST_DATA;
?>

使用 php://input 的注意事项

<?php
// 检查请求内容类型
$contentType = $_SERVER['CONTENT_TYPE'] ?? '';
// 获取原始请求体
$rawBody = file_get_contents('php://input');
类型处理
switch ($contentType) {
    case 'application/json':
        $data = json_decode($rawBody, true);
        break;
    case 'application/x-www-form-urlencoded':
        parse_str($rawBody, $data);
        break;
    case 'multipart/form-data':
        // 文件上传时,php://input 不适用于 multipart/form-data
        // 使用 $_FILES 和 $_POST
        break;
    default:
        // 其他类型
        $data = $rawBody;
}
?>

完整的请求体获取函数

<?php
function getRequestBody() {
    $rawBody = '';
    // 获取原始请求体
    $rawBody = file_get_contents('php://input');
    // 如果没有获取到,尝试其他方式
    if (empty($rawBody)) {
        // 检查是否已填充到全局变量
        if (isset($GLOBALS['HTTP_RAW_POST_DATA'])) {
            $rawBody = $GLOBALS['HTTP_RAW_POST_DATA'];
        }
    }
    return $rawBody;
}
// 使用示例
$body = getRequestBody();
echo "原始请求体: " . $body;
// 解析 JSON
if (!empty($body)) {
    $jsonData = json_decode($body, true);
    if (json_last_error() === JSON_ERROR_NONE) {
        print_r($jsonData);
    }
}
?>

处理不同 HTTP 方法的请求

<?php
// 获取请求方法
$method = $_SERVER['REQUEST_METHOD'];
// 根据请求方法获取数据
switch ($method) {
    case 'POST':
        // 检查内容类型
        if (strpos($_SERVER['CONTENT_TYPE'], 'application/json') !== false) {
            // JSON 数据
            $data = json_decode(file_get_contents('php://input'), true);
        } elseif (strpos($_SERVER['CONTENT_TYPE'], 'multipart/form-data') !== false) {
            // 文件上传,使用 $_POST 和 $_FILES
            $data = $_POST;
        } else {
            // 其他类型的 POST 数据
            $data = $_POST;
            if (empty($data)) {
                $data = json_decode(file_get_contents('php://input'), true);
            }
        }
        break;
    case 'PUT':
    case 'PATCH':
        // PUT/PATCH 请求通常使用原始请求体
        $data = json_decode(file_get_contents('php://input'), true);
        break;
    case 'DELETE':
        // DELETE 请求
        $data = json_decode(file_get_contents('php://input'), true);
        break;
    default:
        // GET 请求
        $data = $_GET;
}
// 输出结果
echo "请求方法: " . $method . "\n";
echo "请求数据: ";
print_r($data);
?>

使用 cURL 测试 API

<?php
// 发送 POST 请求测试
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://example.com/api');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, '{"key":"value"}');
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
?>

最佳实践建议

  1. 优先使用 php://input,它是官方推荐的方式
  2. 处理前检查请求大小,避免内存问题
  3. 根据 Content-Type 进行相应解析
  4. 对于 JSON 数据,使用 json_decode 时注意错误处理
<?php
// 推荐的完整处理方式
function processRequest() {
    // 检查请求大小
    $maxSize = 10 * 1024 * 1024; // 10MB
    $contentLength = $_SERVER['CONTENT_LENGTH'] ?? 0;
    if ($contentLength > $maxSize) {
        http_response_code(413);
        echo json_encode(['error' => '请求体太大']);
        return;
    }
    // 获取原始请求体
    $rawBody = file_get_contents('php://input');
    // 解析数据
    $contentType = $_SERVER['CONTENT_TYPE'] ?? '';
    if (strpos($contentType, 'application/json') !== false) {
        $data = json_decode($rawBody, true);
        if (json_last_error() !== JSON_ERROR_NONE) {
            http_response_code(400);
            echo json_encode(['error' => '无效的 JSON 数据']);
            return;
        }
    } else {
        $data = $rawBody;
    }
    return $data;
}
// 使用
$requestData = processRequest();
?>

选择哪种方法取决于你的 PHP 版本和具体需求。php://input 是所有 PHP 版本都支持且推荐的方式

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