使用 Indy 的 IDTCPClient 从响应流获取 HTML [关闭]

2023-12-29

我有一个前员工创建的组件。它使用 Indy (IDTCPClient) 和以下方法来执行请求(其中“aReadHeader”是 在传入之前构建的预定义 Uri)。

function TMyConnector.GET(aRawHeader: String): String;
begin
if Not Connected then Connected := True;
if Connected then
  begin
  FRawRequest :=  'GET /'+ aRawHeader + ' HTTP/'+HTTPVerText+#13#10+
                  'Host: '+FHost+#13#10+

                  'Cookie: UserHPos=IOGLO00003000090000C000BS; '+
                  'LOSID=qsBiy/wEDCq6tOXFzGbOlTD1lmo5AXdFnCkbzzPn6+qCeheYVyTcumRrjsqh+Hds4Fr2gZDazfDzGN1RA+nnHuQQeBy78ZUgctrZyyy9MnGl2qI/ulkV6EPxAfmmLg/lopRq99f5gAcG/dgtytAJjS+aD5DqtHGrAqjiqgtkwuA=; '+
                  'LoginHPos=IOGLO00003000090000C000BS; '+
                  'UIHPos=IOGLO00003000020000500003; '+
                  'LOSG=61939308-7C83-47ED-B909-2D2D10AD7026; '+
                  'fControllingBusiness=IOGLO000030000900001000050000200001'+#13#10+

                  'Connection: Close'+#13#10+
                  #13#10;

  FSock.Socket.Write(FRawRequest);
  FRawResponse := FSock.Socket.ReadLn(#13#10#13#10,nil);
  Result := FRawResponse;
  if ResponseStream = nil then ResponseStream := TMemoryStream.Create
    else ResponseStream.SetSize(0);
  FSock.Socket.ReadStream(ResponseStream,-1,True);
  if Connected and (Not KeepAlive) then Connected := False;
  end;
end;

询问 FRawResponse 返回的问题

HTTP/1.0 200 OK 内容长度:5560 日期:2013 年 11 月 18 日星期一 15:05:07 GMT 内容类型:text/html;字符集=UTF-8 ...,公共

我怎样才能真正从 ResponseStream 获取这个 html 内容到 HTML

当前存在的方法之一是“GenerateJSON”(参见下面的代码)。我想创建一个名为“GenerateHTML”的

Function StreamToArray(Strm:TStream):TArray<Byte>;
Begin
 Strm.Position := 0;
 SetLength(Result,Strm.Size);
 Strm.Read(Result[0],Strm.Size);
End;


Procedure TMyConnector.GenerateJSON;
begin
 if ResponseStream <> nil then
  Begin
   ResponseJSON_V := TJSONObject.ParseJSONValue(StreamToArray(ResponseStream),0) as TJSONValue; // Note ResponseJSON_V is declared as TJSONValue in TMyConnector);
  End;
end;

所以,我需要

Procedure TMyConnector.GenerateHTML;
begin
 if ResponseStream <> nil then
  Begin
   // result:= html from stream here
  End;
end;

EDIT:

Procedure TMyConnector.GenerateXML;
var
 S: String;
begin
if ResponseStream <> nil then
  Begin
   try
    while FSock.IOHandler.CheckForDataOnSource(30) do
    begin
       S := FSock.IOHandler.InputBufferAsString;
    end;
  finally
    ResponseStr_v:= S;
  end;
  End;
end;

之前的员工显然不知道 Indy's 的存在TIdHTTP组件,或者印地的ReadStream()方法实际上是如何工作的,或者说 HTTP 通常是如何工作的。您应该重写要使用的函数TIdHTTP并让它为您处理所有细节,例如:

function TMyConnector.GET(aRawHeader: String): String;
begin
  FHTTP.ProtocolVersion := ...; // pv1_0 or pv1_1

  // Indy has a TIdCookieManager component that can be attached to
  // the TIdHTTP.CookieManager property, which handles parsing,
  // tracking, and sending back cookies for you for each HTTP
  // request, so this should be re-written to utilize that
  // functionality...
  //
  FHTTP.Request.CustomHeaders.Values['Cookie'] := 'UserHPos=IOGLO00003000090000C000BS; '+
  'LOSID=qsBiy/wEDCq6tOXFzGbOlTD1lmo5AXdFnCkbzzPn6+qCeheYVyTcumRrjsqh+Hds4Fr2gZDazfDzGN1RA+nnHuQQeBy78ZUgctrZyyy9MnGl2qI/ulkV6EPxAfmmLg/lopRq99f5gAcG/dgtytAJjS+aD5DqtHGrAqjiqgtkwuA=; '+
  'LoginHPos=IOGLO00003000090000C000BS; '+
  'UIHPos=IOGLO00003000020000500003; '+
  'LOSG=61939308-7C83-47ED-B909-2D2D10AD7026; '+
  'fControllingBusiness=IOGLO000030000900001000050000200001';

  FHTTP.Request.Connection := 'Close';

  if ResponseStream = nil then
    ResponseStream := TMemoryStream.Create
  else
    ResponseStream.Size := 0;

  try
    try
      FHTTP.Get('http://' + FHost + '/' + aRawHeader, ResponseStream);
    finally
      FRawResponse := FHTTP.Response.RawHeaders.Text;
      Result := FRawResponse;
    end;
  except
    on E: EIdHTTPProtocolException do
    begin
      // HTTP error response. You can grab the error content if you need it...
      WriteStringToStream(ResponseStream, E.ErrorMessage);
    end;
    on E: Exception do
    begin
      // some other error, handle as needed...
    end;
  end;
end;

如果重写使用TIdHTTP不可能,那么你必须更新原来的代码才能真正实现基本的HTTP解析。仅仅调用是不够的ReadStream(), 你必须知道WHEN调用它,并且WHAT传递给它的参数。尝试更多类似这样的事情:

function TMyConnector.GET(aRawHeader: String): String;
var
  Headers: TIdHeaderList;
  Size: integer;

  function InternalReadLn: String;
  begin
    Result := FSock.IOHandler.ReadLn;
    if FSock.IOHandler.ReadLnTimedout then begin
      raise EIdReadTimeout.Create('');
    end;
  end;

  function ChunkSize: integer;
  var
    j: Integer;
    s: string;
  begin
    s := InternalReadLn;
    j := Pos(';', s); {do not localize}
    if j > 0 then begin
      s := Copy(s, 1, j - 1);
    end;
    Result := StrToInt('$' + Trim(s), 0);
  end;

begin
  if Not Connected then Connected := True;
  if Connected then
  begin
    FRawRequest :=  'GET /'+ aRawHeader + ' HTTP/'+HTTPVerText+#13#10+
                    'Host: '+FHost+#13#10+

                    'Cookie: UserHPos=IOGLO00003000090000C000BS; '+
                    'LOSID=qsBiy/wEDCq6tOXFzGbOlTD1lmo5AXdFnCkbzzPn6+qCeheYVyTcumRrjsqh+Hds4Fr2gZDazfDzGN1RA+nnHuQQeBy78ZUgctrZyyy9MnGl2qI/ulkV6EPxAfmmLg/lopRq99f5gAcG/dgtytAJjS+aD5DqtHGrAqjiqgtkwuA=; '+
                    'LoginHPos=IOGLO00003000090000C000BS; '+
                    'UIHPos=IOGLO00003000020000500003; '+
                    'LOSG=61939308-7C83-47ED-B909-2D2D10AD7026; '+
                    'fControllingBusiness=IOGLO000030000900001000050000200001'+#13#10+

                    'Connection: Close'+#13#10+
                    #13#10;

    FSock.IOHandler.Write(FRawRequest);
    FRawResponse := FSock.IOHandler.ReadLn(#13#10#13#10,nil);
    Result := FRawResponse;

    if ResponseStream = nil then ResponseStream := TMemoryStream.Create
    else ResponseStream.Size := 0;

    Headers := TIdHeaderList.Create(QuoteHTTP);
    try
      Headers.Text := FRawResponse;

      if Pos('chunked', LowerCase(Headers.Values['Transfer-Encoding']) > 0 then
      begin
        Size := ChunkSize;
        while Size <> 0 do begin
          FSock.IOHandler.ReadStream(ResponseStream, Size);
          InternalReadLn;
          Size := ChunkSize;
        end;
        repeat until InternalReadLn = '';
      end
      else if Headers.IndexOfName('Content-Length') <> -1 then
      begin
        FSock.IOHandler.ReadStream(ResponseStream, StrToInt64(Headers.Values['Content-Length']), False);
      end
      else
        FSock.IOHandler.ReadStream(ResponseStream, -1, True);
    finally
      Headers.Free;
    end;

    if Connected and (Not KeepAlive) then Connected := False;
  end;
end;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Indy 的 IDTCPClient 从响应流获取 HTML [关闭] 的相关文章

  • 将记录转换为序列化表单数据以通过 HTTP 发送

    有没有办法转换此记录 TError record code Word message String end TState record caption String address Cardinal counters TArray
  • 如何将 JSON 字符串转换为图像?

    我有一个将图像转换为 JSON 数组的应用程序 并将其保存到 blob 字段中 function getImage String var memorystream TMemoryStream jsonArray TJSONArray beg
  • 如何读取注册表项的默认值

    我有一个 Delphi XE2 项目来使用注册表项进行某些操作 所以我定义了以下代码 procedure TMainForm BitBtn01Click Sender TObject var RegistryEntry TRegistry
  • 如何从 WinRT StreamSocket 读取所有可用数据并清空 inputStream?

    我想在向套接字写入新数据之前读取当前正在等待套接字的所有数据 WinRT中的读取方法都是异步的 所以我不能简单地while直到套接字为空 由于我确实想丢弃套接字上的数据 因此我不想使用读取器 而是直接从套接字读取数据IInputStream
  • 如何在Python中获取套接字的外部IP?

    当我打电话时socket getsockname 在套接字对象上 它返回我的机器的内部 IP 和端口的元组 但是 我想找回我的外部IP 最便宜 最有效的方式是什么 如果没有外部服务器的配合 这是不可能的 因为您和另一台计算机之间可能存在任意
  • 运行 pm2 记录错误 SyntaxError: Unexpected token

    我想查看我的项目的日志 Steps 我克隆了一个套接字应用程序 然后我跑npm install pm2 g安装pm2 I run pm2 start 有用 它显示我的套接字应用程序的表格 但如果我跑pm2 logs查看日志 存在这样的错误
  • C 套接字客户端/服务器滞后

    我正在编写一个 C C 客户端 服务器套接字应用程序 此时 客户端每 50 毫秒连接一次服务器并发送一条消息 一切似乎都正常 但数据流并不连续 突然 服务器不再收到任何消息 然后一次收到 5 条消息 有时一切正常 有人知道这种奇怪行为的起源
  • 如何向标准集合编辑器添加图标?

    我有一个自定义控件 它利用TCollection and TCollectionItem 在集合编辑器中 我想向每个列表项添加图标 该列表项由内部TImageList 在其父组件内 集合项本身代表图标 我想在这个编辑器中显示相应的图标 如何
  • 在TImageViewer中,如何获取用户点击图片的位置?

    在TImageViewer控件中 用户可以缩放或平移图片 我的问题是 当用户点击图片时 如何获取用户在图片上的点击位置 尤其是用户可以对图片进行放大 缩小或平移之后 如何获取对应的图片点击位置呢 As shown below How to
  • 类型转换 sockaddr 结构

    我正在尝试学习网络编程 并在这个过程中学习C 我对结构感到困惑sockaddr这是一个通用地址 并且sockaddr in 我的书里是这么说的 因此 我们可以填写 sockaddr in 的字段 然后强制转换 a 指向 它指向 指向 soc
  • 使用 TStringList 的分隔符解析字符串,似乎也解析空格(Delphi)

    我有一个简单的字符串 由某个字符分隔 比如说逗号 我应该能够创建一个 TStringList 并将其分隔符设置为逗号 然后将 DelimitedText 设置为我想要解析的文本 并且应该自动解析它 问题是 当我查看输出时 它还包含空格作为分
  • 如何将数据库查询的行转换为 XML 文件?

    我正在开发一个 Delphi 应用程序 该应用程序需要从一段工作中获取行并将其转换为单个 XML 文件 以便上传到第三方 Web 服务 有没有可用的组件或库可以做到这一点 如果不是 那么构建 DB2XML 转换器的最佳代码方法是什么 我注意
  • 使用项目中的波形文件

    我目前只能通过将波形文件放在已编译的 exe 旁边来播放背景声音 但我实际上想要一个包含波形文件的静态可执行文件 这在Delphi XE2中可能吗 这是我的代码 SndPlaySound Raw wav SND ASYNC or SND L
  • Java/Python 中的快速 IPC/Socket 通信

    我的应用程序中需要两个进程 Java 和 Python 进行通信 我注意到套接字通信占用了 93 的运行时间 为什么通讯这么慢 我应该寻找套接字通信的替代方案还是可以使其更快 更新 我发现了一个简单的修复方法 由于某些未知原因 缓冲输出流似
  • Ruby on Rails:如何使用 TCP 套接字连接 GPS 设备

    ruby 2 3 0p0 2015 12 25 修订版 53290 x86 64 linux 轨道 4 2 4 我正在使用 cloud9 IDE 和 webrick 服务器 我的项目是实时跟踪GPS 我想使用TCP连接与GPS跟踪设备进行通
  • 对象的引用计数

    在我的代码中 我使用一个小的数据存储类 它是在不同的地方创建的 为了避免内存泄漏并简化事情 我想使用引用计数 所以我这样做了 type TFileInfo class TInterfacedObject IInterface 并删除了我对
  • 使用PHP套接字发送和接收数据

    我正在尝试通过 PHP 套接字发送和接收数据 一切正常 但是当我尝试发送数据时 PHP 不发送任何内容 Wireshark 告诉我发送的数据长度为 0 我正在使用这段代码
  • Linux TUN/TAP:无法从 TAP 设备读回数据

    问题是关于如何正确配置想要使用 Tun Tap 模块的 Linux 主机 My Goal 利用现有的路由软件 以下为APP1和APP2 但拦截并修改其发送和接收的所有消息 由Mediator完成 我的场景 Ubuntu 10 04 Mach
  • 在 Delphi 或 C++ Builder 中使用 Chromium Edge WebView2 [重复]

    这个问题在这里已经有答案了 既然 Microsoft Chromium Edge 已经最终确定 是否可以在 Delphi 或 C Builder 中使用它 据我了解 它是基于WebView2成分 是否有一个组件 例如TWebView2或者E
  • 从 Delphi VCL 样式获取特定字形

    我想从 VCL 样式获取特定的位图 并将其设置为按钮上的图像 它实际上是帮助问号 在位图样式编辑器中是来自表单的 btnHelp 图像 要从 VCL 样式获取视觉元素 字形 您必须使用GetElementDetails和TCustomSty

随机推荐