http - 原生 Delphi HTTPClient 是否支持 SNI?
问题描述
我们必须在我们的休息请求中包含 SNI (Server_Name_Indication),因为服务器将在不久的将来托管多个虚拟域。我们使用的是在运行时创建的标准 THTTPClient 组件。一旦我们使用新证书添加新域,我们就会收到异常“服务器证书无效或不存在”(翻译自德语错误文本)
是否有一个特殊的标头值可以像基本身份验证一样存档 SNI?
下面是我们代码的简化版本(无日志记录、无代理、假 URL)。很抱歉,我无法提供我们正在使用的真实 URL。
我们希望我们必须增加 GetRequest 方法,但没有找到任何示例或提示。
unit Unit1;
interface
uses
Winapi.Windows, WinApi.WinHTTP, System.Classes,
Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
System.Net.HTTPClient;
type
TForm1 = class(TForm)
Button1: TButton;
Edit1: TEdit;
procedure Button1Click(Sender: TObject);
private
function PostRequest(const cRequest, cBody: string): string;
public
{ Public declarations }
end;
type
TMyRestClient = class(TObject)
private
fHTTPClient: THTTPClient;
fSysUrl: string;
fUserID: string;
fPassWD: string;
//...
function GetRequest(const cMethod, cUrl: string): IHTTPRequest;
public
constructor Create(const cUrl: string);
destructor Destroy; override;
function Post(const cRequest, cBody: string): string;
//...
property SystemUrl: string read fSysUrl write fSysUrl;
property Username: string read fUserID write fUserID;
property Password: string read fPassWD write fPassWD ;
end;
var
Form1: TForm1;
implementation
uses
System.SysUtils, System.Variants, System.NetEncoding;
{$R *.dfm}
constructor TMyRestClient.Create(const cUrl: string);
begin
fHTTPClient := THTTPClient.Create;
SystemUrl := cUrl;
end;
destructor TMyRestClient.Destroy;
begin
FreeAndNil(fHTTPClient);
inherited Destroy;
end;
function TMyRestClient.GetRequest(const cMethod, cUrl: string): IHTTPRequest;
begin
Result := fHTTPClient.GetRequest(cMethod, cUrl);
Result.AddHeader('content-type', 'appplication/json');
if (Password <> '') then
Result.AddHeader('Authorization', 'Basic ' + TNetEncoding.Base64.Encode(Username + ':' + Password));
end;
function TMyRestClient.Post(const cRequest, cBody: string): string;
var
iRequest: IHTTPRequest;
iResponse: IHTTPResponse;
aBody: TStringStream;
begin
iRequest := GetRequest('POST', Format('%s/%s', [SystemUrl, cRequest]));
aBody := TStringStream.Create(UTF8String(cBody));
try
iRequest.SourceStream := aBody;
iResponse := fHTTPClient.Execute(iRequest);
finally
aBody.DisposeOf;
end;
if (iResponse.StatusCode <> HTTP_STATUS_OK) then
raise Exception.CreateFmt('Post: %s failed (Code %d) %', [cRequest, iResponse.StatusCode, iResponse.StatusText]);
Result := iResponse.ContentAsString;
end;
function TForm1.PostRequest(const cRequest, cBody: string): string;
var
xClient: TMyRestClient;
begin
xClient := TMyRestClient.Create('www.myserver.com/demo');
try
// Basic authentification (not used)
xClient.Username := '';
xClient.Password := '';
Result := xClient.Post(cRequest, cBody);
finally
xClient.DisposeOf
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Edit1.Text := PostRequest('retrieve/paramvalue', '{''PARAM'':''VERSION''}' );
end;
解决方案
推荐阅读
- navigation - 单击后如何关闭此移动菜单(bootstrap5)
- asp.net - 如何使用 JSON 和 ChartJS 制作一个显示某个年龄段人数的饼图?
- sql - Django 外键关系应该是用户到模型还是模型到用户?
- java - 我不知道 ArrayIndexOutOfBoundsException 错误从我的 java 代码中出现在哪里
- r - R:仅当 bool 为 TRUE(条件字符串)时才粘贴()某个字符串?
- javascript - 我在哪里使用 useMemo 和 useCallback?
- html - 需要在 Django 中显示二进制到图像
- regex - 更好的分块正则表达式来满足短字符串?
- java - @ReservedStackAccess 对堆栈溢出特别敏感的方法是什么意思
- networking - 如何创建组策略以将特定用户的域或 URL 列入白名单