J'essaie d'obtenir la réponse et les en-têtes de réponse de CURL en utilisant PHP, spécifiquement pour Content-Disposition: attachment; afin que je puisse retourner le nom de fichier passé dans l'en-tête. Cela ne semble pas être retourné dans curl_getinfo.
J'ai essayé d'utiliser le HeaderFunction pour appeler une fonction pour lire les en-têtes supplémentaires, cependant, je ne peux pas ajouter le contenu à un tableau.
Quelqu'un at-il des idées s'il vous plaît?
Ci-dessous fait partie de mon code qui est une classe wrapper Curl:
...
curl_setopt($this->_ch, CURLOPT_URL, $this->_url);
curl_setopt($this->_ch, CURLOPT_HEADER, false);
curl_setopt($this->_ch, CURLOPT_POST, 1);
curl_setopt($this->_ch, CURLOPT_POSTFIELDS, $this->_postData);
curl_setopt($this->_ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($this->_ch, CURLOPT_USERAGENT, $this->_userAgent);
curl_setopt($this->_ch, CURLOPT_HEADERFUNCTION, 'readHeader');
$this->_response = curl_exec($this->_ch);
$info = curl_getinfo($this->_ch);
...
function readHeader($ch, $header)
{
array_Push($this->_headers, $header);
}
Ici, cela devrait le faire:
curl_setopt($this->_ch, CURLOPT_URL, $this->_url);
curl_setopt($this->_ch, CURLOPT_HEADER, 1);
curl_setopt($this->_ch, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($this->_ch);
$info = curl_getinfo($this->_ch);
$headers = get_headers_from_curl_response($response);
function get_headers_from_curl_response($response)
{
$headers = array();
$header_text = substr($response, 0, strpos($response, "\r\n\r\n"));
foreach (explode("\r\n", $header_text) as $i => $line)
if ($i === 0)
$headers['http_code'] = $line;
else
{
list ($key, $value) = explode(': ', $line);
$headers[$key] = $value;
}
return $headers;
}
La réponse de c.hill est excellente mais le code ne sera pas géré si la première réponse est un 301 ou 302 - dans ce cas, seul le premier en-tête sera ajouté au tableau retourné par get_header_from_curl_response ().
J'ai mis à jour la fonction pour renvoyer un tableau avec chacun des en-têtes.
J'utilise d'abord ces lignes pour créer une variable avec uniquement le contenu de l'en-tête
$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$header = substr($a, 0, $header_size);
Ensuite, je passe $ header à la nouvelle fonction get_headers_from_curl_response () -:
static function get_headers_from_curl_response($headerContent)
{
$headers = array();
// Split the string on every "double" new line.
$arrRequests = explode("\r\n\r\n", $headerContent);
// Loop of response headers. The "count() -1" is to
//avoid an empty row for the extra line break before the body of the response.
for ($index = 0; $index < count($arrRequests) -1; $index++) {
foreach (explode("\r\n", $arrRequests[$index]) as $i => $line)
{
if ($i === 0)
$headers[$index]['http_code'] = $line;
else
{
list ($key, $value) = explode(': ', $line);
$headers[$index][$key] = $value;
}
}
}
return $headers;
}
Cette fonction prendra l'en-tête comme ceci:
HTTP/1.1 302 Found
Cache-Control: no-cache
Pragma: no-cache
Content-Type: text/html; charset=utf-8
Expires: -1
Location: http://www.website.com/
Server: Microsoft-IIS/7.5
X-AspNet-Version: 4.0.30319
Date: Sun, 08 Sep 2013 10:51:39 GMT
Connection: close
Content-Length: 16313
HTTP/1.1 200 OK
Cache-Control: private
Content-Type: text/html; charset=utf-8
Server: Microsoft-IIS/7.5
X-AspNet-Version: 4.0.30319
Date: Sun, 08 Sep 2013 10:51:39 GMT
Connection: close
Content-Length: 15519
Et renvoyez un tableau comme celui-ci:
(
[0] => Array
(
[http_code] => HTTP/1.1 302 Found
[Cache-Control] => no-cache
[Pragma] => no-cache
[Content-Type] => text/html; charset=utf-8
[Expires] => -1
[Location] => http://www.website.com/
[Server] => Microsoft-IIS/7.5
[X-AspNet-Version] => 4.0.30319
[Date] => Sun, 08 Sep 2013 10:51:39 GMT
[Connection] => close
[Content-Length] => 16313
)
[1] => Array
(
[http_code] => HTTP/1.1 200 OK
[Cache-Control] => private
[Content-Type] => text/html; charset=utf-8
[Server] => Microsoft-IIS/7.5
[X-AspNet-Version] => 4.0.30319
[Date] => Sun, 08 Sep 2013 10:51:39 GMT
[Connection] => close
[Content-Length] => 15519
)
)
Un autre ma mise en œuvre:
function getHeaders($response){
if (!preg_match_all('/([A-Za-z\-]{1,})\:(.*)\\r/', $response, $matches)
|| !isset($matches[1], $matches[2])){
return false;
}
$headers = [];
foreach ($matches[1] as $index => $key){
$headers[$key] = $matches[2][$index];
}
return $headers;
}
Utilisé dans le cas, dont le format de demande est:
Hôte: *
J'accepte: *
Longueur du contenu: *
et etc ...
L'utilisation du formulaire array()
pour les rappels de méthode devrait faire fonctionner l'exemple d'origine:
curl_setopt($this->_ch, CURLOPT_HEADERFUNCTION, array($this, 'readHeader'));
Simple et direct
$headers = [];
// Get the response body as string
$response = curl_exec($curl);
// Get the response headers as string
$headerSize = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
// Get the substring of the headers and explode as an array by \r\n
// Each element of the array will be a string `Header-Key: Header-Value`
// Retrieve this two parts with a simple regex `/(.*?): (.*)/`
foreach(explode("\r\n", trim(substr($response, 0, $headerSize))) as $row) {
if(preg_match('/(.*?): (.*)/', $row, $matches)) {
$headers[$matches[1]] = $matches[2];
}
}
Résolution des problèmes:
Voici mon point de vue sur le sujet ;-)
list($head, $body)=explode("\r\n\r\n", $content, 2);
$headers=parseHeaders($head);
function parseHeaders($text) {
$headers=array();
foreach (explode("\r\n", $text) as $i => $line) {
// Special HTTP first line
if (!$i && preg_match('@^HTTP/(?<protocol>[0-9.]+)\s+(?<code>\d+)(?:\s+(?<message>.*))?$@', $line, $match)) {
$headers['@status']=$line;
$headers['@code']=$match['code'];
$headers['@protocol']=$match['protocol'];
$headers['@message']=$match['message'];
continue;
}
// Multiline header - join with previous
if ($key && preg_match('/^\s/', $line)) {
$headers[$key].=' '.trim($line);
continue;
}
list ($key, $value) = explode(': ', $line, 2);
$key=strtolower($key);
// Append duplicate headers - namely Set-Cookie header
$headers[$key]=isset($headers[$key]) ? $headers[$key].' ' : $value;
}
return $headers;
}
La réponse de C.hill est excellente mais se casse lors de la récupération de plusieurs cookies. J'ai fait le changement ici
public function get_headers_from_curl_response($response) {
$headers = array();
$header_text = substr($response, 0, strpos($response, "\r\n\r\n"));
foreach (explode("\r\n", $header_text) as $i => $line)
if ($i === 0) $headers['http_code'] = $line;
else {
list ($key, $value) = explode(': ', $line); $headers[$key][] = $value;
}
return $headers;
}