【问题标题】:TIdHTTP - Get only ResponsecodeTIdHTTP - 仅获取响应代码
【发布时间】:2017-02-26 09:35:54
【问题描述】:

我正在使用TIdHTTP 组件,它是GET 函数。

GET 函数发送一个完整的请求,这很好。

但是,我想从 GET 响应中节省/保存一些流量,并且只想接收位于 HTTP 响应第一“行”中的响应代码。

是否有可能断开连接以节省更多内容的流量?

如前所述,我只需要来自网站的响应代码。

我还考虑过使用 Indy 的 TCP 组件(带有 SSL IOHandler)并制作自己的 HTTP 请求标头,然后接收响应代码并在成功时断开连接 - 但我不知道该怎么做。

【问题讨论】:

  • 这就是 Head 请求的目的,还是我在这里遗漏了什么?
  • @DNR 我不知道这个功能。谢谢你的提示,但是这个函数发送一个 HEAD 请求,但我需要它是一个 GET 请求
  • HEAD 请求与 GET 请求相同,只是它不发送响应内容。这不正是你想要的吗?
  • @DNR HEAD 请求不是 GET 请求...我正在尝试 HEAD 请求的网络服务器导致 405 不允许响应。这就是为什么它首先需要是一个 GET 请求,而我只需要网络服务器响应的前几个字节。
  • @DNR TIdTCPClient 组件呢?我可以制作自己的 HTTP 请求标头,发送它接收前几个字节,并在得到结果后立即断开连接。我只是不知道该怎么做,因为我从来没有使用过这个组件。

标签: delphi indy delphi-10.1-berlin


【解决方案1】:

TIdHTTP 有一个 OnHeadersAvailable 事件,专门用于此任务。它在读取响应标头之后和读取正文内容(如果有)之前触发。它有一个VContinue 输出参数,您可以将其设置为 False 以取消任何进一步的阅读。


更新:我刚刚发现:在OnHeadersAvailable 事件中设置VContinue=False 时,TIdHTTP 将设置Response.KeepAlive=False 并跳过阅读响应正文(到目前为止还可以),但是处理完响应后,TIdHTTP 检查KeepAlive 的值,如果套接字尚未在服务器端关闭(HTTP 1.1 默认使用 keep-alives),则属性 getter 返回 True。这会导致TIdHTTP 不会关闭它的套接字末端,并且会留下任何未读取的响应正文。如果您随后将相同的 TIdHTTP 对象重新用于新的 HTTP 请求,它最终会在看到新请求的响应标头之前处理来自先前响应的任何未读取的正文数据。

您可以通过在调用TIdHTTP.Get() 之前将Request.Connection 属性设置为'close' 来解决此问题。这告诉服务器在发送响应后关闭其套接字连接的结尾(尽管,我刚刚发现在请求 HTTPS url 时,特别是在 HTTP 请求指向 HTTPS 之后,TIdHTTP 清除了Request.Connection 值!)。或者,只需在 TIdHTTP.Get() 退出后调用 TIdHTTP.Disconnect()

我现在已将TIdHTTP 更新为:

  • 在准备 HTTPS 请求时不再清除 Request.Connection

  • 如果有以下任一情况,则关闭其套接字连接的结尾:

    • OnHeadersAvailable 返回VContinue=False

    • 无论服务器的响应如何,Request.Connection 属性(或者,如果连接到代理,则为 Request.ProxyConnection 属性)已设置为 'close'

【讨论】:

  • 有没有办法刷新 OnHeadersAvailable 中的缓冲区?我在这个事件的同一个目标地址上使用了大约 50 个线程。 TIdHeaderList 出于某种原因给了我正文内容,根本没有标题数据。所有线程都有自己的 TIdHTTP 实例和自己的 OnHeadersAvailable 事件。任何想法为什么它向我展示了一些奇怪的身体内容?响应码有时为 -1
  • OnHeadersAvailable 被触发时,TIdHTTP 还没有读取正文内容(尽管它可能已经从套接字读取并缓冲在IOHandler.InputBuffer 中等待读取)。我可以看到出现在TIdHeaderList 中的正文内容的唯一方法是,如果您正在做某事使TIdHTTP 在不关闭套接字的情况下跳过正文内容,然后您在同一个套接字连接上读取另一个 HTTP 请求。它将读取待处理的正文内容而不是下一个请求标头。如果OnHeadersAvailable 返回VContinue=False,则TIdHTTP 应该正在关闭套接字。
  • 我正在使用 VContinue:=False;当我在一个线程中使用多个 TIdHTTP 实例时,响应代码会出现问题。我使用的线程越少,我得到的正确结果(响应代码)就越多。将对此进行进一步调查,并可能对该主题提出新问题。但是,接受您的回答最适合这种情况。
  • 我更新了我的答案。原来TIdHTTP 中存在一些我现在已经修复的错误。
【解决方案2】:

通常你会使用TIdHttp.Head,因为 HEAD 请求就是为了这样做。

如果服务器不接受像 OP 一样的 HEAD 请求,您可以分配您的 TIdHttp 实例的 OnWorkBegin 事件,并在那里调用 TIdHttp(Sender).Disconnect;。这会立即关闭连接,下载不会继续,但您仍然拥有响应代码、内容长度等元数据。

【讨论】:

  • 感谢您的回答。你能给我举个例子吗?我不熟悉 OnWorkBegin 似乎在内容已经完全下载时被调用。
  • 不,不是。那是 OnWorkEnd。您只需分配事件处理程序,您必须放入其中的唯一行就是 Disconnect 调用。
  • 这是一个很好的答案!非常感谢。我也确实将接收缓冲区大小设置为 1,所以我节省了 32kb :)
  • @Benjamin Weiss 我认为你应该接受 Remy 的回答,效果差不多,但他的更优雅。
  • @DNR:嗯,不仅如此,我所描述的是 TIdHTTP 实际上是如何设计使用的,而您的方法是一种解决方法。
猜你喜欢
  • 2011-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-27
  • 2015-03-06
  • 1970-01-01
  • 2018-06-13
  • 2018-02-27
相关资源
最近更新 更多