第十四章-PHP与HTTP协议
一,HTTP 协议详解
HTTP(HyperText Transfer Protocol,超文本传输协议)是互联网上应用最广泛的协议之一,用于客户端(如浏览器)与服务器之间的通信。它是 Web 技术的基石,理解 HTTP 协议是开发 Web 应用的核心基础。以下是 HTTP 协议的全面解析:
一、HTTP 协议基础
1. 协议特性
- 无状态 (Stateless)
每个 HTTP 请求相互独立,服务器默认不保存客户端状态(如用户登录信息)。状态管理需通过 Cookie、Session 或 Token 实现。 - 基于请求-响应模型
- 客户端发送请求(Request) → 服务器返回响应(Response)。
- 支持多种数据格式:HTML、JSON、XML、图片、视频等。
- 灵活可扩展
- 通过 HTTP 头部(Headers) 扩展功能(如缓存控制、内容协商)。
- 支持 HTTPS(HTTP + SSL/TLS)加密传输。
2. 协议版本
版本 | 年份 | 核心改进 |
---|---|---|
HTTP/0.9 | 1991 | 仅支持 GET 方法,返回纯文本 |
HTTP/1.0 | 1996 | 支持 MIME 类型、状态码、Header |
HTTP/1.1 | 1999 | 持久连接、管道化、Host 头 |
HTTP/2 | 2015 | 二进制协议、多路复用、头部压缩 |
HTTP/3 | 2022 | 基于 QUIC 协议(UDP)、减少延迟 |
二、HTTP 消息结构
1. 请求(Request)
GET /index.html HTTP/1.1 # 请求行:方法 + 路径 + 协议版本
Host: www.example.com # 头部字段(Headers)
User-Agent: Mozilla/5.0
Accept: text/html# 空行(分隔头部和消息体)# 消息体(Body,GET 请求通常为空)
-
请求方法 (Methods)
方法 用途 幂等性 GET
获取资源(参数在 URL) 是 POST
提交数据(参数在 Body) 否 PUT
更新完整资源 是 DELETE
删除资源 是 PATCH
更新部分资源 否 HEAD
获取响应头(无 Body) 是 OPTIONS
查询服务器支持的通信选项 是
2. 响应(Response)
HTTP/1.1 200 OK # 状态行:协议版本 + 状态码 + 状态描述
Content-Type: text/html # 头部字段(Headers)
Content-Length: 1234
Date: Mon, 01 Jan 2024 12:00:00 GMT# 空行
<!DOCTYPE html> # 消息体(Body)
<html>...</html>
-
状态码 (Status Codes)
状态码 类别 常见示例 1xx 信息响应 100(继续) 2xx 成功 200(OK)、201(Created) 3xx 重定向 301(永久重定向)、304(未修改) 4xx 客户端错误 400(错误请求)、403(禁止访问) 5xx 服务端错误 500(内部错误)、503(服务不可用)
三、核心机制详解
1. 连接管理
- 短连接 (HTTP/1.0)
每次请求后关闭 TCP 连接,效率低。 - 持久连接 (HTTP/1.1)
- 默认保持 TCP 连接复用(
Connection: keep-alive
)。 - 通过
Content-Length
或Transfer-Encoding: chunked
处理动态内容。
- 默认保持 TCP 连接复用(
- 多路复用 (HTTP/2)
单个 TCP 连接上并行传输多个请求/响应,解决队头阻塞问题。
2. 缓存机制
- 强缓存
Cache-Control: max-age=3600
:资源有效期 1 小时。Expires: Mon, 01 Jan 2024 12:00:00 GMT
(HTTP/1.0,已被取代)。
- 协商缓存
Last-Modified
+If-Modified-Since
:基于时间戳。ETag
+If-None-Match
:基于内容哈希值。
3. 内容协商
客户端通过 Header 声明偏好,服务器返回最合适的内容:
Accept: text/html, application/json
(内容类型)Accept-Language: en-US, zh-CN
(语言)Accept-Encoding: gzip, deflate
(压缩方式)
4. 安全机制
-
HTTPS
- HTTP over SSL/TLS,加密传输数据。
- 通过数字证书验证服务器身份。
-
CORS (跨域资源共享)
Access-Control-Allow-Origin: https://trusted-site.com Access-Control-Allow-Methods: GET, POST
四、HTTP 头部关键字段
常用请求头
字段 | 用途 |
---|---|
Host | 目标域名(HTTP/1.1 必需) |
User-Agent | 客户端标识(浏览器、操作系统) |
Cookie | 发送服务器设置的 Cookie |
Authorization | 认证凭证(如 Bearer <token> ) |
Content-Type | 请求体的 MIME 类型(如 application/json ) |
常用响应头
字段 | 用途 |
---|---|
Set-Cookie | 设置客户端的 Cookie |
Location | 重定向目标 URL(配合 3xx 状态码) |
Content-Encoding | 内容压缩方式(如 gzip ) |
Cache-Control | 缓存策略(如 no-cache ) |
Content-Security-Policy | 防止 XSS 攻击 |
二,常见的HTTP 响应设置
一、基础响应设置
1. 设置 HTTP 状态码
// 直接设置状态码 (PHP >= 5.4)
http_response_code(404); // 返回 404 Not Found// 传统方式(兼容旧版本)
header("HTTP/1.1 403 Forbidden");
2. 设置响应内容类型
// 返回 HTML
header('Content-Type: text/html; charset=utf-8');// 返回 JSON(API 开发必备)
header('Content-Type: application/json; charset=utf-8');// 返回纯文本
header('Content-Type: text/plain');// 返回 XML
header('Content-Type: application/xml');
二、重定向与页面跳转
1. 基础重定向
// 302 临时重定向(默认)
header('Location: /new-page.php');
exit; // 必须立即终止脚本执行// 301 永久重定向
header('Location: /permanent-page.php', true, 301);
exit;
2. 延迟重定向
// 3 秒后跳转
header('Refresh: 3; url=/target-page.php');
echo '即将跳转,请稍候...';
三、缓存控制
1. 禁止浏览器缓存
header('Cache-Control: no-cache, no-store, must-revalidate'); // HTTP/1.1
header('Pragma: no-cache'); // HTTP/1.0
header('Expires: 0'); // 代理服务器缓存
2. 设置资源缓存时间
// 缓存 1 小时(适用于静态资源)
header('Cache-Control: public, max-age=3600');
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 3600) . ' GMT');
四、文件操作相关
1. 文件下载
$filePath = '/path/to/file.zip';header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . basename($filePath) . '"');
header('Content-Length: ' . filesize($filePath));readfile($filePath);
exit;
2. 断点续传支持
header('Accept-Ranges: bytes');
header('Content-Length: ' . filesize($filePath));
五、安全相关头部
1. 防止点击劫持
header('X-Frame-Options: DENY'); // 或 SAMEORIGIN
2. 内容安全策略(CSP)
header("Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.cdn.com");
3. 禁用 MIME 类型嗅探
header('X-Content-Type-Options: nosniff');
六、跨域资源共享(CORS)
1. 简单跨域请求
header('Access-Control-Allow-Origin: *'); // 允许所有域名(慎用)
header('Access-Control-Allow-Origin: https://trusted-site.com'); // 指定域名
2. 预检请求处理
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE');header('Access-Control-Allow-Headers: Content-Type, Authorization');header('Access-Control-Max-Age: 86400'); // 缓存预检结果 24 小时exit;
}
七、Cookie 操作
1. 设置 Cookie
setcookie('user_token', // Cookie 名称'abc123xyz', // 值time() + 3600, // 过期时间(1 小时)'/', // 有效路径'.example.com', // 域名(支持子域名)true, // 仅 HTTPS 传输true // 禁止 JavaScript 访问(HttpOnly)
);
2. 删除 Cookie
setcookie('user_token', '', time() - 3600, '/', '.example.com', true, true);
八、高级场景示例
1. 构建 JSON API
try {$data = ['status' => 'success', 'data' => fetchData()];http_response_code(200);
} catch (Exception $e) {$data = ['status' => 'error', 'message' => $e->getMessage()];http_response_code(500);
}header('Content-Type: application/json');
echo json_encode($data, JSON_UNESCAPED_UNICODE);
exit;
2. 强制下载大文件(内存优化)
$file = fopen('large-file.iso', 'rb');header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="large-file.iso"');while (!feof($file)) {echo fread($file, 8192); // 分块输出ob_flush();flush();
}fclose($file);
exit;
关键注意事项
-
输出顺序问题
- 所有
header()
调用必须在任何实际输出(包括空格和空行)之前 - 使用
ob_start()
开启输出缓冲可避免报错
- 所有
-
编码一致性
header('Content-Type: text/html; charset=utf-8'); // 同时设置 PHP 内部编码 mb_internal_encoding('UTF-8');
-
性能优化
- 避免频繁设置重复头部
- 使用
header_remove()
清除不需要的默认头部
-
安全防护
- 敏感操作后立即调用
session_regenerate_id()
- 使用
header('X-XSS-Protection: 1; mode=block')
启用浏览器 XSS 过滤
- 敏感操作后立即调用
三, PHP模拟 HTTP 请求
一、使用 file_get_contents()
发送请求
适用于简单 GET/POST 请求,需开启 allow_url_fopen
配置。
1. 发送 GET 请求
$url = 'https://api.example.com/data?param1=value1¶m2=value2';
$response = file_get_contents($url);
echo $response;
2. 发送 POST 请求(表单数据)
$url = 'https://api.example.com/submit';
$data = ['key1' => 'value1', 'key2' => 'value2'];$options = ['http' => ['method' => 'POST','header' => 'Content-Type: application/x-www-form-urlencoded','content' => http_build_query($data)]
];
$context = stream_context_create($options);
$response = file_get_contents($url, false, $context);
echo $response;
3. 发送 POST 请求(JSON 数据)
$url = 'https://api.example.com/submit';
$data = json_encode(['name' => 'Alice', 'age' => 30]);$options = ['http' => ['method' => 'POST','header' => "Content-Type: application/json\r\n",'content' => $data]
];
$context = stream_context_create($options);
$response = file_get_contents($url, false, $context);
echo $response;
二、使用 cURL 扩展
功能更强大,支持 HTTPS、头部设置、文件上传等。
1. 基础 GET 请求
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.example.com/data');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 返回响应内容
$response = curl_exec($ch);
curl_close($ch);
echo $response;
2. 发送 POST 请求(表单数据)
$url = 'https://api.example.com/submit';
$data = ['username' => 'test', 'password' => '123456'];$ch = curl_init();
curl_setopt_array($ch, [CURLOPT_URL => $url,CURLOPT_RETURNTRANSFER => true,CURLOPT_POST => true,CURLOPT_POSTFIELDS => http_build_query($data),CURLOPT_HTTPHEADER => ['Content-Type: application/x-www-form-urlencoded']
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
3. 发送 POST 请求(JSON 数据)
$url = 'https://api.example.com/submit';
$data = json_encode(['title' => 'Test', 'content' => 'Hello World']);$ch = curl_init();
curl_setopt_array($ch, [CURLOPT_URL => $url,CURLOPT_RETURNTRANSFER => true,CURLOPT_POST => true,CURLOPT_POSTFIELDS => $data,CURLOPT_HTTPHEADER => ['Content-Type: application/json','Authorization: Bearer abc123xyz']
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
三、处理 HTTPS 与 SSL 验证
1. 忽略 SSL 证书验证(仅限测试环境)
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
2. 指定 CA 证书
curl_setopt($ch, CURLOPT_CAINFO, '/path/to/cacert.pem');
四、文件上传
$filePath = '/path/to/file.jpg';
$data = ['file' => new CURLFile($filePath, 'image/jpeg', 'photo.jpg'),'description' => 'My photo'
];$ch = curl_init();
curl_setopt_array($ch, [CURLOPT_URL => 'https://api.example.com/upload',CURLOPT_POST => true,CURLOPT_POSTFIELDS => $data,CURLOPT_RETURNTRANSFER => true
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
五、处理 Cookies
1. 发送时携带 Cookies
curl_setopt($ch, CURLOPT_COOKIE, 'session_id=abc123; user_token=xyz789');
2. 保存响应 Cookies
curl_setopt($ch, CURLOPT_COOKIEJAR, '/path/to/cookies.txt'); // 保存到文件
curl_setopt($ch, CURLOPT_COOKIEFILE, '/path/to/cookies.txt'); // 读取 Cookies
六、高级配置
1. 设置超时时间载
curl_setopt($ch, CURLOPT_TIMEOUT, 30); // 30 秒超时
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); // 连接超时 10 秒
2. 处理重定向
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // 自动跟随重定向
curl_setopt($ch, CURLOPT_MAXREDIRS, 5); // 最大重定向次数
3. 获取响应头信息
curl_setopt($ch, CURLOPT_HEADER, true); // 包含头信息在输出中$response = curl_exec($ch);
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$headers = substr($response, 0, $headerSize);
$body = substr($response, $headerSize);echo "Headers:\n$headers\nBody:\n$body";
七、错误处理
$ch = curl_init();
// ... 设置选项 ...$response = curl_exec($ch);
if ($response === false) {$error = curl_error($ch);$errno = curl_errno($ch);echo "cURL 错误 ($errno): $error";
} else {$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);echo "HTTP 状态码: $httpCode\n响应内容:\n$response";
}
curl_close($ch);
八、完整示例:调用 REST API
function callApi($url, $method = 'GET', $data = null, $headers = []) {$ch = curl_init();$options = [CURLOPT_URL => $url,CURLOPT_RETURNTRANSFER => true,CURLOPT_CUSTOMREQUEST => strtoupper($method),CURLOPT_HTTPHEADER => $headers];if ($method !== 'GET' && $data !== null) {$options[CURLOPT_POSTFIELDS] = is_array($data) ? json_encode($data) : $data;}curl_setopt_array($ch, $options);$response = curl_exec($ch);$error = curl_error($ch);$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);curl_close($ch);return ['code' => $httpCode,'data' => json_decode($response, true),'error' => $error];
}// 调用示例
$result = callApi('https://api.example.com/users','POST',['name' => 'Alice', 'email' => 'alice@example.com'],['Content-Type: application/json', 'Authorization: Bearer token123']
);print_r($result);
注意事项
- 安全建议
- 生产环境务必启用 SSL 证书验证
- 敏感数据(如 API 密钥)不要硬编码在代码中
- 对用户输入做严格过滤
- 性能优化
- 复用 cURL 句柄(使用
curl_init()
一次,多次请求) - 设置合理的超时时间
- 复用 cURL 句柄(使用
- 第三方库推荐
如需更复杂功能,可使用:- Guzzle HTTP:
composer require guzzlehttp/guzzle
- Symfony HTTP Client:
composer require symfony/http-client
- Guzzle HTTP: