Delphi 的TNetHTTPC客户端后代支持http2

icomxhvb  于 2023-01-20  发布在  其他
关注(0)|答案(2)|浏览(528)

我正在尝试从 Delphi 10.3.1 Windows客户端应用程序通过gRPC与Google Cloud Speech通信。为此,通信需要使用http2作为协议,数据需要双向异步传输。
Delphi 包含TNetHTTPClient,TNetHTTPRequest使用它进行http通信,使用调试器,我发现System.Net.HttpClient.Win.pas中的TWinHTTPClient在内部用于通信。
为了添加http2支持,我在System.Net.HttpClient.Win.pas的TWinHTTPClient.DoExecuteRequest中的第1360行插入了两行:

LOptionValue := 1;//WINHTTP_PROTOCOL_FLAG_HTTP2;
    WinHttpSetOption(LRequest.FWRequest, WINHTTP_OPTION_ENABLE_HTTP_PROTOCOL, @LOptionValue, sizeof(LOptionValue));

添加上述代码后,组件正在使用http2,我通过gRPC成功调用Google Cloud Speech Sync Request端点验证了这一点。
然而,我的方法有两个主要缺点:
1.它需要修改 Delphi 源代码。
1.它不支持数据的异步双向传输,对此,我认为有必要使用一个类似于OnDataReceived的事件,该事件可以在连接没有关闭的情况下触发。
我试图找到一个可以用修改后的组件TMyNetHTTPClient替换TNetHTTPClient的点,但没有成功。
所以,问题是:如何基于TWinHTTPClient创建TNetHTTPClient替代品,该替代品支持http2并在不关闭连接的情况下实现OnDataReceived事件?

gywdnpxw

gywdnpxw1#

它不是基于TNetHTTPClient的,但是grijjy已经为Windows和Linux开源了一个HTTP 2 Delphi 客户端。
您可以在此处找到它-https://github.com/grijjy/DelphiScalableClientSockets

5q4ezhmt

5q4ezhmt2#

有点晚了,对不起:)我不知道如何实现数据的异步双向传输。我知道TWinHTTPClient是如何构造的。不幸的是,正如您所发现的,由于TWinHTTPClient隐藏在单元的实现中,您无法扩展它。
你可以复制那个单元,做必要的修改,然后使用修改后的类,复制它一点也不理想,因为它是一个超过2000行的单元,但不幸的是没有办法。
但是如何构造修改后的TWinHttpClient,因为通常你根本不会直接构造一个TWinHttpClient?这有点棘手,特别是如果你想使用其他类(如TNetHttpClient),它们在内部构造自己的HttpClient。
TWinHTTPClient将自己注册为HTTPHTTPS的处理程序,该单元本身通过调用TUrlSchemas.RegisterURLClientScheme来执行此操作。
您可以取消注册TWinHttpClient类,然后注册您自己的类,如下所示:

TURLSchemes.UnRegisterURLClientScheme('HTTP');
  TURLSchemes.UnRegisterURLClientScheme('HTTPS');
  TURLSchemes.RegisterURLClientScheme(TYourWinHttpClient, 'HTTP');
  TURLSchemes.RegisterURLClientScheme(TYourWinHttpClient, 'HTTPS');

之后,您可以调用THttpClient.create,它实际上不是构造函数,而是一个 *class函数 *,它将调用TURLSchemes来获取注册类的示例。
也就是说,它找到类,并调用该类的CreateInstance类函数。CreateInstance是TUrlClient(最终基类)的虚拟工厂方法。类应重写该方法以创建并返回自身的示例。
这是一个奇怪的构造。THttpClient不仅是各种平台特定的后代的基类,而且还是它们的工厂。我碰巧遇到了这个逻辑(和这个问题),当我试图创建一个用于单元测试的THttpClient后代时,遇到了一些令人惊讶的行为。我还不确定这是天才还是疯狂,或者两者兼而有之:D
TUrlClientTHttpClientTWinHttpClient是RTL类,旨在从代码示例化。
TNetHTTPClient是一个TComponent,你可以把它放在TForm或TDataModule上来配置设计时。在运行时,当发出请求时,它会在内部使用THttpClient。如果你注册了它,它应该使用你修改过的版本。

相关问题