【问题标题】:How to handle "100 continue" HTTP message?如何处理“100 continue”HTTP 消息?
【发布时间】:2010-06-03 09:33:42
【问题描述】:

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

据我了解,服务器应该读取标头,在连接上发回HTTP/1.1 100 Continue 响应,将流读取到Content-Length 上的值,然后发回真正的响应代码(通常是@ 987654325@ 但任何其他有效的 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
<

【问题讨论】:

  • HTTP/1.1 100 Continue后面不需要空行吗?
  • 有一个。它没有被记录的事实似乎是 cURL 的显示问题。
  • 澄清一下,发回一个完全有效的 HTTP 响应 (HTTP/1.1 100 Continue\r\n\r\n) 而不仅仅是字符串 "HTTP/1.1 100 Continue"。 cURL 客户端将一直等待,直到它接收到这两个 序列,如果它放弃,它将输出(在详细模式下)消息“等待 100-继续完成”。
  • 我刚刚找到的 100-continue 示例的要点仅供参考:gist.github.com/trevorrowe/c2353ab959c6852a2bd7

标签: http post curl


【解决方案1】:

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

您的服务器应该仅根据来自客户端的标头来验证请求,即如果请求无效,不要发送“100 Continue”而是实际的 http 错误,例如403. 这应该首先阻止客户端发布我理解的数据是往返服务器的全部点(即客户端等待“100 Continue”)。

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

【讨论】:

  • 感谢您的回答。你是对的:这是一个古老的问题,但你得到它非常正确。我真正的问题是,“100”不是成功错误代码:客户端应始终检查实际响应中包含的返回代码。显然,这不是 cURL 正在做的事情。
  • “这应该会阻止客户端发布数据”——这可能是 RFC 中最容易被误解的部分。缺少 100-Continue 不会阻止客户端继续,RFC 明确指出客户端可以继续发送请求正文。实际上,处理响应的唯一有效方法是发送正文或断开连接。
  • 如果人们对 curl 邮件列表感兴趣,关于 curl / web 服务器的这种误解的其他有用背景:More on POST and PUT with 100-continue
【解决方案2】:

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

curl_easy_setopt (curl_handle, CURLOPT_FAILONERROR, 1L);

根据libcURLdocumentation,这个选项 “如果返回的 HTTP 代码等于或大于 400,则告诉库静默失败。”

此外,文档明确指出“默认操作是正常返回页面,忽略该代码。”

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

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

“此方法不是故障安全的,在某些情况下不成功的响应代码会漏掉,尤其是在涉及身份验证时(响应代码 401 和 407)。”

【讨论】:

  • 我正在使用命令行工具,但 -f 标志似乎不会影响工具的行为方式。从那以后,我决定编写自己的客户端来正确处理这些失败的上传。谢谢你的回答,虽然
【解决方案3】:

其实100 Continue header后面应该有真正的header

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

$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);
}

【讨论】:

  • 好吧,我确实在代码 100 答案之后发送了一个真实的标题。不过,cURL 似乎并不在意。
【解决方案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】:

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

    【讨论】:

    • 似乎缺少的行是一个错误。我检查了代码,“100 continue”后面有一个空行
    猜你喜欢
    • 2010-09-12
    • 1970-01-01
    • 2013-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多