php curl 分离header和body信息

本文介绍如何使用PHP的cURL库发送HTTP GET请求,并从响应中分离出Header和Body部分。提供了两种方法实现这一目标:一种是利用curl_getinfo()获取头部长度,另一种则是依据HTTP响应的结构特性进行分割。

php curl 分离header和body信息


php中可以通过curl来模拟http请求,同时可以获取http response header和body,当然也设置参数可以只获取其中的某一个。当设置同时获取response header和body时候,它们会一同作为结果返回。这时需要我们自己来分离它们。

下面代码是模拟向google一个http GET请求

function httpGet() {
    $url = 'http://www.google.com.hk';
    
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HEADER, TRUE);    //表示需要response header
    curl_setopt($ch, CURLOPT_NOBODY, FALSE); //表示需要response body
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, FALSE);
    curl_setopt($ch, CURLOPT_AUTOREFERER, TRUE);
    curl_setopt($ch, CURLOPT_TIMEOUT, 120);
    
    $result = curl_exec($ch);
    
    if (curl_getinfo($ch, CURLINFO_HTTP_CODE) == '200') {
        return $result;
    }
    
    return NULL;
}

调用上述方法后看到如下类似输出:

HTTP/1.1 200 OK
Date: Tue, 09 Jul 2013 14:21:08 GMT
Expires: -1
Cache-Control: private, max-age=0
Content-Type: text/html; charset=UTF-8
Set-Cookie: PREF=ID=75e996a7ad21f47b:FF=0:NW=1:TM=1373379668:LM=1373379668:S=TTLQQN-jwGDYnkkY; expires=Thu, 09-Jul-2015 14:21:08 GMT; path=/; domain=.google.com.hk
Set-Cookie: NID=67=PPu7FfFeuZqwfsrUifgzjidX4JZxxCPLe9xFHjdXhfHpzs3gaykFSH5uGXy2esWTlp_rdqIYkjFDMollzI_sA-8owxD3mDh6KCRwdMa9-g5VChj0E5XAGNjo9d-sZfLN; expires=Wed, 08-Jan-2014 14:21:08 GMT; path=/; domain=.google.com.hk; HttpOnly
P3P: CP="This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657 for more info."
Server: gws
X-XSS-Protection: 1; mode=block
X-Frame-Options: SAMEORIGIN
Transfer-Encoding: chunked

<!doctype html><html itemscope="itemscope" itemtype="http://schema.org/WebPage"><head><meta itemprop="image" content="/images/google_favicon_128.png"><title>Google</title><script>(function(){
window.google={kEI:"VBzcUdWuHOmtiQf64IHoCw",getEI:function(a){for(var b;a&&(!a.getAttribute||!(b=a.getAttribute("eid")));
……

这里可以看到结果中header和body信息是在一起的,那么如何分离它们呢。方法有二种,一是通过curl自带的curl_getinfo()方法获取头的长度,然后使用substr来分割字符串。示例代码如下:

$response = curl_exec($ch);

if (curl_getinfo($ch, CURLINFO_HTTP_CODE) == '200') {
    $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
    $header = substr($response, 0, $headerSize);
    $body = substr($response, $headerSize);
}

第二种方法基于header和body是通过两个回车换行来分割的,所以可以通过如下代码实现:

$response = curl_exec($ch);

if (curl_getinfo($ch, CURLINFO_HTTP_CODE) == '200') {
    list($header, $body) = explode("\r\n\r\n", response, 2);
}
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>天气预报API请求工具</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { background: linear-gradient(135deg, #1a2a6c, #b21f1f, #fdbb2d); color: #333; min-height: 100vh; padding: 20px; } .container { max-width: 1200px; margin: 0 auto; background: rgba(255, 255, 255, 0.95); border-radius: 15px; padding: 30px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2); } h1 { text-align: center; margin-bottom: 20px; color: #2c3e50; } h2 { color: #3498db; margin-bottom: 15px; padding-bottom: 10px; border-bottom: 2px solid #eee; } .card { background: #f8f9fa; border-radius: 10px; padding: 20px; margin-bottom: 20px; } .error-card { background: #ffecec; border-left: 4px solid #e74c3c; } .success-card { background: #e8f6ef; border-left: 4px solid #2ecc71; } .code-container { background: #2d3748; color: #e2e8f0; padding: 15px; border-radius: 8px; overflow-x: auto; margin: 15px 0; font-family: 'Consolas', 'Monaco', monospace; line-height: 1.5; } .form-group { margin-bottom: 15px; } label { display: block; margin-bottom: 5px; font-weight: bold; color: #2c3e50; } input[type="text"], select { width: 100%; padding: 10px; border: 2px solid #ddd; border-radius: 5px; font-size: 16px; } button { background: #3498db; color: white; padding: 12px 20px; border: none; border-radius: 5px; cursor: pointer; font-size: 16px; font-weight: bold; transition: background 0.3s; margin-right: 10px; } button:hover { background: #2980b9; } .response-info { margin-top: 20px; } .response-header { color: #7f8c8d; font-size: 14px; margin-bottom: 5px; } .response-data { font-size: 16px; color: #2c3e50; } .note { background: #fff3cd; padding: 15px; border-radius: 8px; margin: 20px 0; color: #856404; border-left: 4px solid #ffc107; } .solution { background: #d4edda; padding: 15px; border-radius: 8px; margin: 20px 0; color: #155724; border-left: 4px solid #28a745; } .flex-container { display: flex; gap: 20px; flex-wrap: wrap; } .flex-item { flex: 1; min-width: 300px; } .weather-result { background: white; border-radius: 10px; padding: 20px; margin-top: 20px; box-shadow: 0 4px 10px rgba(0,0,0,0.1); } .weather-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; } .city-name { font-size: 24px; font-weight: bold; color: #2c3e50; } .weather-info { display: flex; justify-content: space-between; align-items: center; } .temperature { font-size: 48px; font-weight: bold; color: #e74c3c; } .weather-desc { font-size: 20px; color: #34495e; } .weather-details { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px; margin-top: 20px; } .detail-item { display: flex; flex-direction: column; padding: 15px; background: #f8f9fa; border-radius: 8px; } .detail-label { font-size: 14px; color: #7f8c8d; margin-bottom: 5px; } .detail-value { font-size: 18px; font-weight: bold; color: #2c3e50; } @media (max-width: 768px) { .flex-container { flex-direction: column; } .weather-info { flex-direction: column; text-align: center; } } </style> </head> <body> <div class="container"> <h1>🌤️ 天气预报API请求工具</h1> <div class="card error-card"> <h2>问题分析</h2> <p>您的API请求返回了错误:<strong>"地区代码或名称错误,请参考基础数据"</strong></p> <p>根据API文档,请求参数应该使用<code>areaCh</code>而不是<code>areaCn</code>,并且应该移除不必要的null参数。</p> </div> <div class="flex-container"> <div class="flex-item"> <div class="card"> <h2>原始代码(有问题)</h2> <div class="code-container"> $url = "http://getweather.api.bdymkt.com/lundear/weather1d?areaCn=北京&areaCode=null&ip=null&lat=null&lng=null&need3hour=null&needIndex=null&needObserve=null&needalarm=null&need1hour=null"; </div> </div> </div> <div class="flex-item"> <div class="card"> <h2>修正后的代码</h2> <div class="code-container"> $url = "http://getweather.api.bdymkt.com/lundear/weather1d?areaCh=" . urlencode($city); </div> </div> </div> </div> <div class="solution"> <h2>解决方案</h2> <p>根据API文档,您需要:</p> <ol> <li>使用<code>areaCh</code>参数而不是<code>areaCn</code></li> <li>移除所有不必要的null参数</li> <li>对城市名称进行URL编码</li> <li>确保使用正确的AppCode</li> </ol> </div> <div class="card"> <h2>测试天气预报请求</h2> <form id="weatherForm"> <div class="form-group"> <label for="city">城市名称</label> <input type="text" id="city" name="city" value="北京" required> </div> <div class="form-group"> <label for="appCode">AppCode</label> <input type="text" id="appCode" name="appCode" placeholder="输入您的AppCode" required> </div> <button type="button" onclick="testRequest()">测试请求</button> <button type="button" onclick="viewPHPCode()">查看PHP代码</button> </form> <div id="result" class="weather-result" style="display: none;"> <h3>请求结果</h3> <div id="responseData" class="code-container"></div> </div> <div id="weatherDisplay" class="weather-result" style="display: none;"> <div class="weather-header"> <div class="city-name" id="resultCity">城市名称</div> <div class="date" id="resultDate">日期</div> </div> <div class="weather-info"> <div class="temperature" id="resultTemp">--°C</div> <div class="weather-desc" id="resultWeather">天气状况</div> </div> <div class="weather-details"> <div class="detail-item"> <span class="detail-label">湿度</span> <span class="detail-value" id="resultHumidity">--%</span> </div> <div class="detail-item"> <span class="detail-label">风向</span> <span class="detail-value" id="resultWindDir">--</span> </div> <div class="detail-item"> <span class="detail-label">风力</span> <span class="detail-value" id="resultWindPower">--</span> </div> <div class="detail-item"> <span class="detail-label">气压</span> <span class="detail-value" id="resultPressure">-- hPa</span> </div> </div> </div> </div> <div class="card"> <h2>修正后的PHP代码</h2> <div class="code-container"> <?php // 设置城市名称 $city = "北京"; // 设置请求头 $headers = array(); $appCode = "您的AppCode"; // 替换为您的实际AppCode array_push($headers, "X-Bce-Signature:AppCode/" . $appCode); array_push($headers, "Content-Type: application/json;charset=UTF-8"); // 构建请求URL - 使用areaCh参数并移除不必要的参数 $url = "http://getweather.api.bdymkt.com/lundear/weather1d?areaCh=" . urlencode($city); // 初始化cURL $curl = curl_init(); curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "GET"); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); curl_setopt($curl, CURLOPT_FAILONERROR, false); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_HEADER, true); // 执行请求 $response = curl_exec($curl); // 检查错误 if (curl_errno($curl)) { echo "cURL错误: " . curl_error($curl); } else { // 分离头部响应体 $header_size = curl_getinfo($curl, CURLINFO_HEADER_SIZE); $header = substr($response, 0, $header_size); $body = substr($response, $header_size); // 输出结果 echo "头部信息:\n"; echo $header . "\n\n"; echo "响应体:\n"; $data = json_decode($body, true); if (json_last_error() === JSON_ERROR_NONE) { print_r($data); } else { echo $body; } } // 关闭cURL curl_close($curl); ?> </div> </div> <div class="note"> <h2>注意事项</h2> <ul> <li>请将"您的AppCode"替换为实际的AppCode</li> <li>确保服务器支持cURL扩展</li> <li>城市名称需要准确,可以参考API文档中的基础数据</li> <li>如果仍然遇到问题,请检查AppCode是否有权限访问该API</li> </ul> </div> </div> <script> function testRequest() { const city = document.getElementById('city').value; const appCode = document.getElementById('appCode').value; if (!city || !appCode) { alert('请填写城市名称AppCode'); return; } // 模拟API请求 - 实际使用时需要替换为真实的PHP后端 document.getElementById('result').style.display = 'block'; document.getElementById('responseData').textContent = '正在发送请求到: http://getweather.api.bdymkt.com/lundear/weather1d?areaCh=' + encodeURIComponent(city); // 模拟响应数据 setTimeout(() => { // 这里是模拟的成功响应 const mockResponse = { code: 0, desc: "成功", data: { cityInfo: { areaCn: city, areaId: "101010100" }, now: { temp: "25", weather: "晴", WD: "东南风", WS: "3级", SD: "45%", qy: "1010" }, date: new Date().toLocaleDateString('zh-CN', { year: 'numeric', month: 'long', day: 'numeric', weekday: 'long' }) } }; document.getElementById('responseData').textContent = JSON.stringify(mockResponse, null, 2); // 显示解析后的天气信息 document.getElementById('weatherDisplay').style.display = 'block'; document.getElementById('resultCity').textContent = mockResponse.data.cityInfo.areaCn; document.getElementById('resultDate').textContent = mockResponse.data.date; document.getElementById('resultTemp').textContent = mockResponse.data.now.temp + "°C"; document.getElementById('resultWeather').textContent = mockResponse.data.now.weather; document.getElementById('resultHumidity').textContent = mockResponse.data.now.SD; document.getElementById('resultWindDir').textContent = mockResponse.data.now.WD; document.getElementById('resultWindPower').textContent = mockResponse.data.now.WS; document.getElementById('resultPressure').textContent = mockResponse.data.now.qy + " hPa"; }, 1000); } function viewPHPCode() { const appCode = document.getElementById('appCode').value; if (!appCode) { alert('请先填写AppCode'); return; } const city = document.getElementById('city').value; // 显示PHP代码 const phpCode = `<?php // 设置城市名称 $city = "${city}"; // 设置请求头 $headers = array(); $appCode = "${appCode}"; array_push($headers, "X-Bce-Signature:AppCode/" . $appCode); array_push($headers, "Content-Type: application/json;charset=UTF-8"); // 构建请求URL $url = "http://getweather.api.bdymkt.com/lundear/weather1d?areaCh=" . urlencode($city); // 初始化cURL $curl = curl_init(); curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "GET"); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); curl_setopt($curl, CURLOPT_FAILONERROR, false); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_HEADER, true); // 执行请求 $response = curl_exec($curl); // 检查错误 if (curl_errno($curl)) { echo "cURL错误: " . curl_error($curl); } else { // 分离头部响应体 $header_size = curl_getinfo($curl, CURLINFO_HEADER_SIZE); $header = substr($response, 0, $header_size); $body = substr($response, $header_size); // 输出结果 echo "头部信息:\\n"; echo $header . "\\n\\n"; echo "响应体:\\n"; $data = json_decode($body, true); if (json_last_error() === JSON_ERROR_NONE) { print_r($data); } else { echo $body; } } // 关闭cURL curl_close($curl); ?>`; document.getElementById('result').style.display = 'block'; document.getElementById('responseData').textContent = phpCode; document.getElementById('weatherDisplay').style.display = 'none'; } </script> </body> </html> 请将该代码的核心内容提取出来
最新发布
09-05
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值