Как обрабатывать HTTP-сообщение "100 продолжай"?
Я пишу упрощенный HTTP-сервер, который будет принимать запросы PUT в основном от cURL в качестве клиента, и у меня возникли некоторые проблемы с обработкой Expect: 100-continue
заголовок.
Насколько я понимаю, сервер должен прочитать заголовок, отправить обратно HTTP/1.1 100 Continue
ответ на соединение, читать поток до значения на Content-Length
а затем отправить обратно реальный код ответа (обычно HTTP/1.1 200 OK
но любой другой действительный ответ HTTP должен сделать).
Ну, это именно то, что делает мой сервер. Проблема в том, что, по-видимому, если я отправлю 100 Continue
ответ, cURL не сообщает о любом последующем коде ошибки HTTP и предполагает, что загрузка прошла успешно. Например, если загрузка отклонена из-за характера содержимого (происходит проверка основных данных), я хочу, чтобы вызывающий клиент обнаружил проблему и действовал соответствующим образом.
Я что-то упускаю из виду?
edit: вот пример вывода из cURL со вторичным заголовком, содержащим ошибку:
> PUT /test1%2Epdf HTTP/1.1
> Authorization: Basic xxxx
> User-Agent: curl/7.20.0 (i386-pc-win32) libcurl/7.20.0 OpenSSL/0.9.8l zlib/1.2.3
> Host: localhost
> Accept: */*
> Content-Length: 24
> Expect: 100-continue
>
< HTTP/1.1 100 Continue
< HTTP/1.1 415 Unsupported Media Type
< Connection: close
< Content-Type: text/xml
< Content-Length: 289
<
5 ответов
Если вы используете libcURL для написания клиентской программы, убедитесь, что вы установили CURLOPT_FAILONERROR
возможность 1
, Например, в C вы бы сделали что-то вроде:
curl_easy_setopt (curl_handle, CURLOPT_FAILONERROR, 1L);
В соответствии с документацией libcURL, эта опция "сообщает библиотеке о сбое в автоматическом режиме, если возвращаемый HTTP-код равен или больше 400".
Кроме того, в документации ясно сказано, что "действием по умолчанию будет возвращение страницы в обычном режиме, игнорируя этот код".
Если вы используете инструмент командной строки curl, просто добавив -f
или же --fail
в вашу команду curl вызовет поведение, подобное описанному выше. Это также описано в справочной странице curl.
Обратите внимание, что оба эти метода не являются отказоустойчивыми, как четко указано в документации:
"Этот метод не является отказоустойчивым, и бывают случаи, когда неуспешные коды ответов проскальзывают, особенно когда задействована аутентификация (коды ответов 401 и 407)".
Я знаю, что это старо, но вот мое понимание "100 Продолжить"
Предполагается, что ваш сервер проверяет запрос на основе только заголовка от клиента, т. Е. Если запрос недействителен, не отправляйте "100 Continue", а вместо этого фактическую ошибку http, например, 403. Это должно помешать клиенту опубликовать данные, которые я понимаю В этом весь смысл обращения к серверу (т.е. клиент ожидает "100 Continue").
Если вы проверяете фактические опубликованные данные, то вам необходимо применить протокол более высокого уровня, то есть отправить свою ошибку, завернутую в действительный HTTP-ответ. Да, это похоже на ограничение, и я не предполагаю, что это ограничение протокола; более вероятная путаница клиента, связанная с обработкой ответа сервера более одного раза.
Разрабатывая ответ ВАС, и все еще используя PHP в качестве примера:
Возможно, что несколько 100 Continue
заголовки могут быть получены. Я использую следующее, чтобы медленно проработать заголовки и удалить каждый из 100 Continue
ответы, если они существуют:
<?php
// a little setup first
$ch = curl_init();
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_HEADER,1);
// etc...
$str = curl_exec($ch);
// the goods
$delimiter = "\r\n\r\n"; // HTTP header delimiter
// check if the 100 Continue header exists
while ( preg_match('#^HTTP/[0-9\\.]+\s+100\s+Continue#i',$str) ) {
$tmp = explode($delimiter,$str,2); // grab the 100 Continue header
$str = $tmp[1]; // update the response, purging the most recent 100 Continue header
} // repeat
// now we just have the normal header and the body
$parts = explode($delimiter,$str,2);
$header = $parts[0];
$body = $parts[1];
?>
На самом деле должен быть настоящий заголовок после 100 Продолжить заголовок
Итак, я обычно делаю это на стороне клиента.
$contents=curl_exec($ch);
list( $header, $contents ) = explode( "\r\n\r\n", $contents , 2);
if(strpos($header," 100 Continue")!==false){
list( $header, $contents) = explode( "\r\n\r\n", $contents , 2);
}
Попробуйте добавить пустую строку (CRLF) после строки 100 Continue (см. RFC 2616, раздел 6),