如何处理"100继续"HTTP消息?

Ste*_*ane 31 post curl http

我正在编写一个简单的HTTP服务器,它将接受主要来自cURL的PUT请求作为客户端,并且我在处理Expect: 100-continue标头时遇到了一些问题.

据我了解,服务器应该读取标头,HTTP/1.1 100 Continue在连接上发回响应,读取流到值Content-Length,然后发回真实的响应代码(通常HTTP/1.1 200 OK但任何其他有效的HTTP应答都应该这样做).

嗯,这正是我的服务器所做的.问题是,显然,如果我发送100 Continue答案,cURL无法报告任何后续的HTTP错误代码并假定上传成功.例如,如果由于内容的性质而导致上传被拒绝(存在基本数据检查),我希望调用客户端检测问题并采取相应措施.

我错过了一些明显的东西吗

编辑:这是来自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
<
Run Code Online (Sandbox Code Playgroud)

bro*_*ekk 23

我知道这是旧的,但这是我对"100继续"的理解

您的服务器应该基于来自客户端的标头验证请求,即如果请求无效,请不要发送"100 Continue"而是发送实际的http错误,例如403.这应该阻止客户端发布我理解的数据是第一个到服务器(即客户端等待"100继续")往返的全部要点.

如果您要验证实际发布的数据,那么您需要在此处应用更高级别的协议,即发送包含在有效HTTP响应内容中的错误.是的,这似乎是限制,我不假设它的协议限制; 更有可能是客户端混淆不得不多次处理服务器响应.

  • 谢谢你的回答.你是对的:这是一个老问题,但你得到它非常正确.我真正的问题是,"100"不是成功的错误代码:客户端应该始终检查实际响应中包含的返回代码.显然,这不是cURL正在做的事情. (4认同)
  • “这应该阻止客户端发布数据”——这可能是 RFC 中最容易被误解的部分。缺少 100-Continue 并不妨碍客户端继续,RFC 明确规定客户端可以继续发送请求正文。实际上,处理响应的唯一有效方法是发送正文或断开连接。 (2认同)

blo*_*osh 13

如果您使用libcURL编写客户端程序,请确保将CURLOPT_FAILONERROR选项设置为1.例如,在C中,您可以执行以下操作:

curl_easy_setopt (curl_handle, CURLOPT_FAILONERROR, 1L);
Run Code Online (Sandbox Code Playgroud)

根据libcURL 文档,如果返回的HTTP代码等于或大于400,则此选项"告诉库无提示失败".

此外,文档清楚地表明"默认操作是正常返回页面,忽略该代码".

如果您正在使用curl命令行工具,只需添加-f--fail插入curl命令将导致与上述类似的行为.这也在curl 手册页中描述.

请注意,这两种方法都不是故障安全的,正如文档中明确指出的那样:

"这种方法不是故障安全的,并且有时会出现非成功的响应代码,特别是涉及认证时(响应代码401和407)."


YOU*_*YOU 6

实际上在100 Continue标题后应该有真正的标题

所以,我通常在客户端这样做.

$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);
}
Run Code Online (Sandbox Code Playgroud)


zam*_*uts 5

详细说明您的答案,并仍以 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];
?>
Run Code Online (Sandbox Code Playgroud)