Подтвердить что ты не робот

Как обрабатывать 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
<
4b9b3361

Ответ 1

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

curl_easy_setopt (curl_handle, CURLOPT_FAILONERROR, 1L);

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

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

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

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

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

Ответ 2

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

Предполагается, что ваш сервер должен проверять запрос на основе заголовка только от клиента, то есть, если запрос недействителен, не отправляйте "100 Continue", а фактическую ошибку HTTP, а именно. 403. Это должно помешать клиенту опубликовать данные, которые, как я понимаю, является целым пунктом перехода на сервер (т.е. Клиент, ожидающий "100 Продолжить" ) в первую очередь.

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

Ответ 3

На самом деле должен быть реальный заголовок после 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

Разрабатывая на ВАС ответ и все еще используя 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];
?>

Ответ 5

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