I try to send a certificate with my POST request without the server requesting it first, preemtive speaking.
With Indy it works perfectly fine like this:
procedure TMyExampleClass.GetPassword(var Password: String);
begin
password := '';
end;
var
http: TIdHTTP;
ssl: TIdSSLIOHandlerSocketOpenSSL;
request, response: TStringStream;
begin
certfile := 'c:\temp\certfile.pfx';
http := TIdHTTP.Create;
ssl := TIdSSLIOHandlerSocketOpenSSL.Create(http);
request := TStringStream.Create('', TEncoding.UTF8);
response := TStringStream.Create('', TEncoding.UTF8);
try
ssl.SSLOptions.SSLVersions := [sslvTLSv1_2];
ssl.SSLOptions.CertFile := certfile;
ssl.SSLOptions.KeyFile := certfile;
ssl.SSLOptions.Mode := sslmBoth;
ssl.OnGetPassword := GetPassword;
http.IOHandler := ssl;
http.Request.ContentType := 'application/json; charset=utf-8';
http.Request.UserAgent := 'MySpecialClient';
http.Request.CustomHeaders.Clear;
http.Request.CustomHeaders.FoldLines := false; // without it doesn't work, dunno why
http.Request.CustomHeaders.Values['Ocp-Apim-Subscription-Key'] := 'topsecretsubscriptionkey';
http.Request.CustomHeaders.Values['Signature'] := 'calculatedsignature'; // doesn't matter for this case, usually it's a procedure that calcs the signature by it's streamcontent + certificate
http.HTTPOptions := [hoForceEncodeParams, hoNoProtocolErrorException, hoWantProtocolErrorContent];
request.WriteString(payload); // payload is param of this method; const payload: string;
request.Position := 0;
http.Post('https://myexample.com/v1/api/message', request, response);
response.SaveToFile('c:\temp\test.json');
finally
response.Free;
request.Free;
http.Free;
end;
end;
Now I have to switch to Overbyte ICS for async support but it doesn't work with this code:
procedure TMyExampleClass.AddHeaders(Sender: TObject; const Method: String; Headers: TStrings);
begin
Headers.Add('Ocp-Apim-Subscription-Key: topsecretsubscriptionkey');
end;
var
http: TSslHttpCli;
ssl: TSslContext;
request, response: TStringStream;
//errormsg: string;
begin
http := TSslHttpCli.Create(nil);
ssl := TSslContext.Create(nil);
request := TStringStream.Create('', TEncoding.UTF8);
response := TStringStream.Create('', TEncoding.UTF8);
try
request.WriteString(payload);
request.Position := 0;
ssl.SslCertFile := 'c:\temp\certfile.pfx';
//LoadFromFileEx('c:\temp\certfile.pfx', croYes, croYes, '', errormsg)
http.SslContext := ssl;
http.Agent := 'MySpecialClient';
http.ContentTypePost := 'application/json; charset=utf-8';
http.OnBeforeHeaderSend := AddHeaders;
http.URL := 'https://myexample.com/v1/api/message';
http.SendStream := request;
http.RcvdStream := response;
http.Post;
response.SaveToFile('c:\temp\test.json');
finally
response.Free;
request.Free;
ssl.Free;
http.Free;
end;
end;
I don't find the right method, property, what so ever to load the pfx-cert and transmit it preemptiv.
The exception I get is the following:
Debugger Exception Notification
Project MyExampleProject.exe raised exception class EHttpException with message 'httpPOST: Error# 11 Abort on Exception: Error on reading certificate lines - No PEM Content Found'.
Any idea how to load the pfx-cert? The pfx-cert also contains the private key.