如何处理“100继续”HTTP消息?

时间:2010-06-03 09:33:43

标签: http post curl

我正在编写一个简单的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
<

5 个答案:

答案 0 :(得分:23)

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

您的服务器应该基于来自客户端的标头验证请求,即如果请求无效,发送“100 Continue”,而是实际的http错误,例如, 403.这应该可以防止客户首先将数据发送到服务器(即等待“100继续”的客户端)的全部数据。

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

答案 1 :(得分:11)

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

curl_easy_setopt (curl_handle, CURLOPT_FAILONERROR, 1L);

根据libcURL documentation,此选项 “如果返回的HTTP代码等于或大于400,则告诉库无声地失败。”

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

如果您使用的是curl命令行工具,只需将-f--fail添加到curl命令中,就会产生与上述类似的行为。这也在curl man page中描述。

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

  

“此方法不是故障安全的,并且有时会出现非成功的响应代码,尤其是涉及身份验证时(响应代码401和407)。”

答案 2 :(得分: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);
}

答案 3 :(得分: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];
?>

答案 4 :(得分:3)

尝试在100 Continue行后添加一个空行(CRLF)(参见RFC 2616, Section 6),