Есть ли способ настроить php так, чтобы он всегда устанавливал $_SERVER['CONTENT_LENGTH']?
Я работаю на клиенте carddav. В качестве сервера я использую davical v. 0.9.9.6. Я не понимаю, почему я получаю недопустимую ошибку типа контента, когда заголовки http содержат правильное значение. Я смотрю в исходный код и нашел это условие:
if ( isset($_SERVER['CONTENT_LENGTH']) && $_SERVER['CONTENT_LENGTH'] > 7) {...
После небольшого исследования я нашел набор php $_SERVER['CONTENT_LENGTH']
только с методом POST и загрузкой файла. Есть ли способ настроить php, чтобы всегда устанавливать $_SERVER['CONTENT_LENGTH']
? Я спрашиваю в общем, не только для этого случая...
// РЕДАКТИРОВАТЬ Я делаю HTTP PUT-запрос к davical серверу (используя php curl).
PUT /caldav.php/testuser/contacts/newc.vcf HTTP/1.1
Host: davical
Content-Type: text/vcard;
BEGIN:VCARD
VERSION:3.0
FN:ME
...
На давической стороне находится условие тестирования CONTENT_LENGTH, которое не установлено. Значит, это давняя ошибка?
// РЕДАКТИРОВАТЬ 2
Наконец-то я это понял! Запрос PUT с обратным вызовом обратного вызова требует установки INFILE_SIZE с помощью curl_setopt(...). Автоматическое значение отсутствует, и вводить поле Content-Length вручную в заголовок также неправильно. Пример (неверный):
// PUT REQUEST
curl_setopt($ch,CURLOPT_HTTPHEADER,"Content-Length: $length"); //mistake
curl_setopt($ch,CURLOPT_PUT,true);
curl_setopt($ch,CURLOPT_READFUNCTION,array($this,'readfunc'));
....
--------------------------------------------------------------
// WIRESHARK TCP STREAM DUMP
PUT /caldav.php/testuser/contacts/novy.vcf HTTP/1.1
Authorization: Basic xxxxxxxxxxxxxxx
Host: davical
Accept: */*
Content-Type: text/vcard
Content-Length: xxx
Expect: 100-continue
HTTP/1.1 100 Continue
155
BEGIN:VCARD
VERSION:3.0
...
END:VCARD
0
HTTP/1.1 200 OK
----------------------------------------------------------------
// On server side
isset($_SERVER['CONTENT_LENGTH'])==false
Второй (правильный) пример
// PUT REQUEST
curl_setopt($ch,CURLOPT_INFILESIZE,$length);
curl_setopt($ch,CURLOPT_PUT,true);
curl_setopt($ch,CURLOPT_READFUNCTION,array($this,'readfunc'));
....
--------------------------------------------------------------
// WIRESHARK TCP STREAM DUMP
PUT /caldav.php/testuser/contacts/novy.vcf HTTP/1.1
Authorization: Basic xxxxxxxxxxxxxxx
Host: davical
Accept: */*
Content-Type: text/vcard
Content-Length: xxx
Expect: 100-continue
HTTP/1.1 100 Continue
BEGIN:VCARD
VERSION:3.0
...
END:VCARD
HTTP/1.1 200 OK
----------------------------------------------------------------
// On server side
isset($_SERVER['CONTENT_LENGTH'])==true
3 ответа
Только запросы, которые имеют тело запроса, имеют заголовок запроса длины содержимого (или, по крайней мере, только тогда, когда это имеет смысл), и поэтому $_SERVER
переменная установлена.
Если вам нужно, чтобы он всегда был установлен (я думаю, что это фальшивка), вы можете сделать это самостоятельно в самом начале вашего сценария:
isset($_SERVER['CONTENT_LENGTH']) && $_SERVER['CONTENT_LENGTH'] = 0;
Предполагая, что если он не установлен, он имеет нулевую длину. Смотрите также Улучшенная обработка HTTP-запросов в PHP.
Хотя я никогда не использовал CONTENT_LENGHT, я могу сказать вам, почему это, вероятно, происходит:
В запросе вам не нужно устанавливать заголовок Content-Lenght... ЭТО НЕ ОБЯЗАТЕЛЬНО. За исключением особых ситуаций. Если ваш POST-контент имеет тип "multipart / form-data", становится необходимым использовать контент-длину для каждой части, потому что каждая часть отделена границей и каждая часть будет иметь свои собственные заголовки...
Например:
Content-Type: MultiPart/Form-Data
Boundary: @FGJ4823024562DGGRT3455
MyData=1&Username=Blabla&Password=Blue
@FGJ4823024562DGGRT3455==
Content-Type: image/jpef:base64
Content-Lenght: 256
HNSIFRTGNOHVDFNSIAH$5346twSADVni56hntgsIGHFNR$Iasdf==
Итак, вот грубый пример того, как работает многокомпонентный запрос, вы видите, что вторая часть имеет длину содержимого. Вот почему иногда устанавливается длина содержимого, а иногда нет, потому что вам нужно прочитать байты X, прежде чем найти другую границу и извлечь правильные данные.
Это не значит, что ваш сервер никогда не отправит его в других случаях, но мои 2 цента - это именно тот случай, который есть сейчас. Это потому, что вы находитесь не в режиме POST, а в некоторых других режимах.
Вы могли бы, вероятно, установить их самостоятельно. Зачем вам нужно, чтобы эти значения были установлены? И что они должны установить?
Возможно, вам не хватает информации о $_SERVER['CONTENT_TYPE'] или $_SERVER['CONTENT_LENGTH'], как и я. На POST-запросах они доступны в дополнение к перечисленным выше.
-> http://www.php.net/manual/en/reserved.variables.server.php