Я использую PHP 5.3.5 для Windows, и я не нашел pecl_http.dll
, который работает с моей установкой.
Итак, мой вопрос:
Как мне получить функциональность http_parse_headers
без использования PECL?
Я использую PHP 5.3.5 для Windows, и я не нашел pecl_http.dll
, который работает с моей установкой.
Итак, мой вопрос:
Как мне получить функциональность http_parse_headers
без использования PECL?
Вы можете получить расширение для Windows в
Это один из файлов php_http-5.3-*-x86.zip
. Проверьте, какой PHP вы установили и выберите правильный, например. мой PHP - это php-5.3.6- nts-Win32-VC9 -x86, поэтому мне нужен php_http-5.3- nts-svn20091125-vc9 -x86.zip.
Загрузите zip и извлеките файл php_http.dll в свою папку расширения. Папка расширения должна быть папкой /ext в каталоге установки php. Если вы не уверены, откройте файл php.ini и выполните поиск по этим строкам:
; Directory in which the loadable extensions (modules) reside.
; http://php.net/extension-dir
; extension_dir = "./"
; On windows:
extension_dir = .\ext
Значение для extension_dir - это место, где вы должны поместить dll. Если вы не знаете, где находится ваш php.ini, откройте командную строку и выполните
php --ini
Это скажет вам, где находится ваш php.ini. Он выведет что-то вроде
Configuration File (php.ini) Path: C:\Windows
Loaded Configuration File: C:\php5\php-5.3.6-nts-Win32-VC9-x86\php.ini
Scan for additional .ini files in: (none)
Additional .ini files parsed: (none)
После того, как вы скопировали dll, добавьте расширение в свой php.ini, чтобы включить его. Найдите, где он говорит что-то вроде
;;;;;;;;;;;;;;;;;;;;;;
; Dynamic Extensions ;
;;;;;;;;;;;;;;;;;;;;;;
Здесь должно быть несколько строк:
;extension=php_sybase_ct.dll
extension=php_tidy.dll
;extension=php_xmlrpc.dll
extension=php_xsl.dll
;extension=php_zip.dll
Добавьте следующую строку:
extension=php_http.dll
Сохраните php.ini и введите в командной строке следующее:
php --ri http
Теперь вы должны получить довольно обширный результат, начиная с
http
HTTP Support => enabled
Extension Version => 1.7.0-dev
… more stuff
Это означает, что вы успешно установили расширение и можете использовать его сейчас.
Обратите внимание, что для того, чтобы загрузить это расширение в Windows, вам необходимо загрузить следующие расширения PHP: hash, iconv и SPL.
На странице документации, первый комментарий:
if( !function_exists( 'http_parse_headers' ) ) {
function http_parse_headers( $header )
{
$retVal = array();
$fields = explode("\r\n", preg_replace('/\x0D\x0A[\x09\x20]+/', ' ', $header));
foreach( $fields as $field ) {
if( preg_match('/([^:]+): (.+)/m', $field, $match) ) {
$match[1] = preg_replace('/(?<=^|[\x09\x20\x2D])./e', 'strtoupper("\0")', strtolower(trim($match[1])));
if( isset($retVal[$match[1]]) ) {
$retVal[$match[1]] = array($retVal[$match[1]], $match[2]);
} else {
$retVal[$match[1]] = trim($match[2]);
}
}
}
return $retVal;
}
}
Кроме того, вы можете прочитать, как установить расширение PECL в Windows, честно говоря, я ничего не знаю об этом.
Это также снято с Документация PHP для http_parse_headers. Когда я сравнил его с ответом @Berry Langerak (используя microtime
), я обнаружил, что он в среднем на 17% быстрее, используя образец из 10 заголовков (по-видимому, потому, что он не использует регулярные выражения).
if (!function_exists('http_parse_headers')) {
function http_parse_headers($raw_headers) {
$headers = array();
$key = '';
foreach(explode("\n", $raw_headers) as $i => $h) {
$h = explode(':', $h, 2);
if (isset($h[1])) {
if (!isset($headers[$h[0]]))
$headers[$h[0]] = trim($h[1]);
elseif (is_array($headers[$h[0]])) {
$headers[$h[0]] = array_merge($headers[$h[0]], array(trim($h[1])));
}
else {
$headers[$h[0]] = array_merge(array($headers[$h[0]]), array(trim($h[1])));
}
$key = $h[0];
}
else {
if (substr($h[0], 0, 1) == "\t")
$headers[$key] .= "\r\n\t".trim($h[0]);
elseif (!$key)
$headers[0] = trim($h[0]);
}
}
return $headers;
}
}
Примечание: это включает исправление маленькая ошибка, которую автор указывает в более позднем комментарии.
Функция регулярных выражений
+0,00035881996
0.00036096572
0.00034999847
0.00043797492
0.00033497810В среднем: 0.000368547434
Эта функция
+0,00006198883
0.00006604194
0.00007104873
0.00006413459
0.00006389617Среднее значение 0.000065422052
Так как я не мог найти какую-либо функцию, которая вела себя точно так же, как PECL один раз, я написал свой собственный, по сравнению с другими, это оказалось довольно быстро...
function dirtyHeaderParser($headers, $strict = true){
$arr = array();
$s = strtok($headers, ':');
while ($s){
if ( ($s[0] === ' ') || ($s[0] === "\t") ){
if (count($arr) != 0){
$tail = strtok('');
$tail = "{$s}:{$tail}";
$v = strtok($tail, "\n");
if (is_array($arr[$key])){
end($arr[$key]);
$last = key($arr[$key]);
$arr[$key][$last] = "{$arr[$key][$last]}\n{$v}";
reset($arr[$key]);
} else {
$arr[$key] = "{$arr[$key]}\n{$v}";
}
}
} else {
$v = strtok("\n");
if ($v){
$key = strtolower($s);
if (((strpos($key, "\n") !== false) || (strpos($key, "\t") !== false) || (strpos($key, " ") !== false)) && $strict) {
return false;
}
if (array_key_exists($key, $arr)){
if (!is_array($arr[$key])){
$arr[$key] = array($arr[$key]);
}
$arr[$key][] = trim($v);
} else {
$arr[$key] = trim($v);
}
} else {
break;
}
}
$s = strtok(':');
}
return (count($arr) == 0) ? false : $arr;
}
Строгий режим означает, что он вернет false
, если заголовок содержит \n
, пробел или \t
.
Он поддерживает несколько заголовков строк и двойные значения заголовков (с несколькими строками), если кто-то найдет что-то не так, как версия PECL, я был бы рад, если вы оставите комментарий.
Здесь представлена модифицированная версия страницы документации, которая работает так же, как версия PECL:)
function http_parse_headers( $header ) {
$retVal = array();
$fields = explode("\r\n", preg_replace('/\x0D\x0A[\x09\x20]+/', ' ', $header));
foreach( $fields as $field ) {
if( preg_match('/([^:]+): (.+)/m', $field, $match) ) {
$match[1] = preg_replace('/(?<=^|[\x09\x20\x2D])./e', 'strtoupper("\0")', strtolower(trim($match[1])));
if( isset($retVal[$match[1]]) ) {
if ( is_array( $retVal[$match[1]] ) ) {
$i = count($retVal[$match[1]]);
$retVal[$match[1]][$i] = $match[2];
}
else {
$retVal[$match[1]] = array($retVal[$match[1]], $match[2]);
}
} else {
$retVal[$match[1]] = trim($match[2]);
}
}
}
return $retVal;
}
function parse_headers($headers)
{
$headers = preg_replace('/^\r\n/m', '', $headers);
$headers = preg_replace('/\r\n\s+/m', ' ', $headers);
preg_match_all('/^([^: ]+):\s(.+?(?:\r\n\s(?:.+?))*)?\r\n/m', $headers . "\r\n", $matches);
$result = array();
foreach ($matches[1] as $key => $value)
$result[$value] = (array_key_exists($value, $result) ? $result[$value] . "\n" : '') . $matches[2][$key];
return $result;
}
К сожалению, для функции, представленной на странице документации, если имеется более двух одинаковых заголовков (например, Set-Cookie), структура массива будет неправильной, например:
[Set-Cookie] => Array
(
[0] => Array
(
[0] => AWESOMESESSIONID=xQ5TRl1GXDQcQCXytfb1PK!-744872953!NONE; Path=/cte-lps2s-test2/; Secure
[1] => AWESOME_SESSH_c25c28d0-b763-11df-979f23a029aa77=%2Fcte-lps2s-test2; Path=/
)
[1] => MOREAWESOME=2_uGgNpo2-jm-CjfaefLzjFhmmP-y3HzwNZKE0gsTeP+; Path=/; Secure
)
Следующая модификация кода исправит эту ошибку (см. комментарий):
if( !function_exists( 'http_parse_headers' ) ) {
function http_parse_headers( $header )
{
$retVal = array();
$fields = explode("\r\n", preg_replace('/\x0D\x0A[\x09\x20]+/', ' ',$header));
foreach( $fields as $field ) {
if( preg_match('/([^:]+): (.+)/m', $field, $match) ) {
$match[1] = preg_replace('/(?<=^|[\x09\x20\x2D])./e', 'strtoupper("\0")', strtolower(trim($match[1])));
// We need to check if an array of values has already been created, to maintain the correct level in the $retVal array.
if(is_array($retVal[$match[1]])) {
$retVal[$match[1]] []= $match[2];
}
else {
$retVal[$match[1]] = array($retVal[$match[1]], $match[2]);
}
} else {
$retVal[$match[1]] = trim($match[2]);
}
}
return $retVal;
}
}
Ненавижу продолжать такой старый поток, который уже так долго, но этот является превосходным, потому что:
(Возможно, вам понадобится код, чтобы проверить, существует ли расширение)
function http_parse_headers ($raw) {
$res = [];
foreach (explode("\n", $raw) as $h) {
$h = explode(':', $h, 2);
$first = trim($h[0]);
$last = trim($h[1]);
if (array_key_exists($first, $res)) {
$res[$first] .= ", " . $last;
} else if (isset($h[1])) {
$res[$first] = $last;
} else {
$res[] = $first;
}
}
return $res;
}