Как обрабатывать HTTP-сообщение "100 продолжай"? - PullRequest
30 голосов
/ 03 июня 2010

Я пишу упрощенный HTTP-сервер, который будет принимать запросы PUT в основном от cURL в качестве клиента, и у меня возникла небольшая проблема с обработкой заголовка Expect: 100-continue.

Насколько я понимаю, сервер должен прочитать заголовок, отправить ответ HTTP/1.1 100 Continue на соединение, прочитать поток до значения на Content-Length и затем отправить реальный код ответа (обычно *). 1006 * но любой другой действительный ответ 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 ]

23 голосов
/ 16 января 2012

Я знаю, что это старо, но вот мое понимание "100 Продолжить"

Предполагается, что ваш сервер проверяет запрос на основе только заголовка от клиента, т. Е. Если запрос недействителен, не отправляет «100 Продолжить», но вместо этого возникает фактическая ошибка http, например. 403. Это должно помешать клиенту публиковать данные, которые, как я понимаю, представляют собой весь смысл приема-передачи на сервер (т. Е. Клиент ожидает «100 Continue») в первую очередь.

Если вы проверяете фактические опубликованные данные, то вам необходимо применить протокол более высокого уровня, то есть отправить ошибку, обернутую в действительный HTTP-ответ. Да, это похоже на ограничение, и я не предполагаю, что это ограничение протокола; более вероятная путаница клиента при необходимости обрабатывать ответ сервера более одного раза.

12 голосов
/ 31 октября 2011

Если вы используете libcURL для написания клиентской программы, убедитесь, что для параметра CURLOPT_FAILONERROR установлено значение 1. Например, в C вы должны сделать что-то вроде:

curl_easy_setopt (curl_handle, CURLOPT_FAILONERROR, 1L);

Согласно документации libcURL , эта опция msgstr "сообщает библиотеке о сбое в автоматическом режиме, если возвращаемый HTTP-код равен или превышает 400."

Кроме того, в документации ясно сказано, что «действием по умолчанию будет возвращение страницы в обычном режиме, игнорируя этот код».

Если вы используете инструмент командной строки curl, простое добавление -f или --fail в команду curl вызовет поведение, подобное описанному выше. Это также описано в man-странице curl .

Обратите внимание, что оба эти метода не являются отказоустойчивыми, как четко указано в документации:

"Этот метод не является отказоустойчивым, и в некоторых случаях проскакивают неуспешные коды ответа, особенно когда используется аутентификация (коды ответа 401 и 407)."

6 голосов
/ 03 июня 2010

На самом деле после 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);
}
4 голосов
/ 26 февраля 2014

Обработка ответа ВАС, и все еще использование 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];
?>
3 голосов
/ 03 июня 2010

Попробуйте добавить пустую строку (CRLF) после строки 100 Continue (см. RFC 2616, Раздел 6 ),

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...