Delphi XE5 TRESTRequest получает ssl3_read_bytes: сбой квитирования оповещения sslv3 - PullRequest
0 голосов
/ 30 мая 2019

Я получаю ошибку

Запрос REST не выполнен! Ошибка подключения по SSL. Ошибка: 14094410: SSL подпрограммы: ssl3_read_bytes: сбой квитирования оповещения sslv3

с использованием компонентов TREST, вот пример кода - полный код устройства ниже
Кажется, что это специфично для ссылки, например другие https: звонки работают нормально

function Getcall_UsingRest : String;
var
  fRstclnt1: TRESTClient;
  fRstrqst1: TRESTRequest;
  fRstrspns1: TRESTResponse;
begin
  result := '';
  try
    fRstclnt1:= TRESTClient.Create('https://au-api.basiq.io');
    fRstrqst1:= TRESTRequest.Create(nil);
    fRstrspns1:= TRESTResponse.Create(nil);
    try
      fRstrqst1.Client := fRstclnt1;
      fRstrqst1.Response := fRstrspns1;

      fRstrqst1.Execute;
      result := fRstrspns1.Content;
    finally
      fRstclnt1.Free;
      fRstrqst1.Free;
      fRstrspns1.Free;
    end;
  except
    on E:Exception do begin
      result := e.Message;
    end;
  end;
end;

Я пытался исправить следующее, но я не смог заставить его работать

с использованием компонента TIdHTTP я получаю ту же ошибку

function Getcall_UsingHTTP_WithSameIssue : String;
var
  fIdHTTP1: TIdHTTP;
  fIdSSLIOHandlerSocketOpenSSL1: TIdSSLIOHandlerSocketOpenSSL;
  fresp: TMemoryStream;
  fMySL : TStringList;
begin
  result := '';
  try
    fIdHTTP1:= TIdHTTP.Create(nil);
    try
      fIdSSLIOHandlerSocketOpenSSL1 := TIdSSLIOHandlerSocketOpenSSL.Create(fIdHTTP1);
      fIdHTTP1.IOHandler := fIdSSLIOHandlerSocketOpenSSL1;

      fresp := TMemoryStream.Create;
      fMySL := TStringList.Create;
      try
        fIdHTTP1.Get('https://au-api.basiq.io', fresp);
        fresp.Position := 0;
        fMySL.LoadFromStream( fresp );
        result := fMySL.Text;
      finally
        fMySL.Free;
        fresp.Free;
      end;
    finally
      fIdHTTP1.Free;
    end;
  except
    on E:Exception do begin
      result := e.Message;
    end;
  end;
end;

есть исправление для этого, которое должно поставить

procedure OnStatusInfoEx(ASender: TObject; const AsslSocket: PSSL;
  const AWhere, Aret: TIdC_INT; const AType, AMsg: String);
begin
  SSL_set_tlsext_host_name(AsslSocket, Request.Host);
end;

на fIdSSLIOHandlerSocketOpenSSL1.OnStatusInfoEx: = OnStatusInfoEx;

компонент TIdSSLIOHandlerSocketOpenSSL скрыт глубоко в TRESTClient, и я не смог найти способ проверить, могу ли я применить вышеуказанное исправление для работы с TRESTClient

Может кто-нибудь помочь с тем, как получить тест, чтобы иметь возможность общаться


вот полный исходный код для приведенных выше примеров

unit RestExample;

interface
uses
  System.Generics.Collections
, REST.Types
, REST.Client
, sysutils
, IdHTTP
, IdSSLOpenSSL
, IdSSLOpenSSLHeaders, IdCTypes
, system.Classes
;

function Getcall_UsingRest : String;
function Getcall_UsingHTTP_WithSameIssue : String;
function Getcall_UsingHTTP_WithFix : String;

type
  TCustomIdHTTP = class(TIdHTTP)
  public
    constructor Create(AOwner: TComponent);
  private
    procedure OnStatusInfoEx(ASender: TObject; const AsslSocket: PSSL; const AWhere, Aret: TIdC_INT; const AType, AMsg: String);
  end;

implementation


function Getcall_UsingRest : String;
var
  fRstclnt1: TRESTClient;
  fRstrqst1: TRESTRequest;
  fRstrspns1: TRESTResponse;
begin
  result := '';
  try
    fRstclnt1:= TRESTClient.Create('https://au-api.basiq.io');
    fRstrqst1:= TRESTRequest.Create(nil);
    fRstrspns1:= TRESTResponse.Create(nil);
    try
      fRstrqst1.Client := fRstclnt1;
      fRstrqst1.Response := fRstrspns1;

      fRstrqst1.Execute;
      result := fRstrspns1.Content;
    finally
      fRstclnt1.Free;
      fRstrqst1.Free;
      fRstrspns1.Free;
    end;
  except
    on E:Exception do begin
      result := e.Message;
    end;
  end;
end;

function Getcall_UsingHTTP_WithSameIssue : String;
var
  fIdHTTP1: TIdHTTP;
  fIdSSLIOHandlerSocketOpenSSL1: TIdSSLIOHandlerSocketOpenSSL;
  fresp: TMemoryStream;
  fMySL : TStringList;
begin
  result := '';
  try
    fIdHTTP1:= TIdHTTP.Create(nil);
    try
      fIdSSLIOHandlerSocketOpenSSL1 := TIdSSLIOHandlerSocketOpenSSL.Create(fIdHTTP1);
      fIdHTTP1.IOHandler := fIdSSLIOHandlerSocketOpenSSL1;

      fresp := TMemoryStream.Create;
      fMySL := TStringList.Create;
      try
        fIdHTTP1.Get('https://au-api.basiq.io', fresp);
        fresp.Position := 0;
        fMySL.LoadFromStream( fresp );
        result := fMySL.Text;
      finally
        fMySL.Free;
        fresp.Free;
      end;
    finally
      fIdHTTP1.Free;
    end;
  except
    on E:Exception do begin
      result := e.Message;
    end;
  end;
end;

function Getcall_UsingHTTP_WithFix : String;
var
  fTCustomIdHTTP: TCustomIdHTTP;
  fresp: TMemoryStream;
  fMySL : TStringList;
begin
  result := '';
  try
    fTCustomIdHTTP:= TCustomIdHTTP.Create(nil);
    try
      fresp := TMemoryStream.Create;
      fMySL := TStringList.Create;
      try
        fTCustomIdHTTP.Get('https://au-api.basiq.io', fresp);
        fresp.Position := 0;
        fMySL.LoadFromStream( fresp );
        result := fMySL.Text;
      finally
        fMySL.Free;
        fresp.Free;
      end;
    finally
      fTCustomIdHTTP.Free;
    end;
  except
    on E:Exception do begin
      result := e.Message;
    end;
  end;

end;

{ TCustomIdHTTP }

constructor TCustomIdHTTP.Create(AOwner: TComponent);
begin
  IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
  with IOHandler as TIdSSLIOHandlerSocketOpenSSL do begin
    OnStatusInfoEx := Self.OnStatusInfoEx;
  end;
  inherited Create(AOwner);
end;

procedure TCustomIdHTTP.OnStatusInfoEx(ASender: TObject; const AsslSocket: PSSL;
  const AWhere, Aret: TIdC_INT; const AType, AMsg: String);
begin
  SSL_set_tlsext_host_name(AsslSocket, Request.Host);
end;

end.
...