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