Elavon Get Token, Postman convert to Lazarus TIdHTTP protocol unknown / missing lazarus / 38-Networking and Web Programming ---------------------------------------------------------------------- RedOctober · 2021-05-21 17:26 Platform:  Lazarus 2.0.10,  FPC 3.2.0, Windows Server 2016, Indy 10.6.2.3662 I am trying to convert a working Postman request to a Lazarus TIdHTTP request.  I'm getting a "Protocol unknown" error.  Can someone let me know what I am doing wrong?  Thanks in advance. Here is the Postman request: Code: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {        "info": {                "_postman_id": "95a1529d-5dd5-4714-9a28-823f4c363fd3",                "name": "transactionToken",                "schema": "https://schema.getpostma n.com/json/collection/v2.1.0/collection.json"        },        "item": [                {                        "name": "Transaction Token",                        "request": {                              "method": "POST",                                "header": [                                      {                                              "key": "Content-Type",                                              "name": "Content-Type",                                              "value": "application/x-www-form-urlencoded",                                              "type": "text"                                      }                                ],                              "body": {                                        "mode": "urlencoded",                                        "urlencoded": [                                              {                                                      "key": "ssl_merchant_id",                                                      "value": "",                                                      "type": "text"                                              },                                              {                                                        "key": "ssl_user_id",                                                      "value": "",                                                      "type": "text"                                                },                                              {                                                      "key": "ssl_pin",                                                      "value": "",                                                      "type": "text"                                              },                                                {                                                        "key": "ssl_transaction_type",                                                      "value": "ccsale",                                                      "type": "text"                                              },                                                {                                                      "key": "ssl_amount",                                                      "value": "1.00",                                                      "type": "text"                                              }                                      ]                                },                              "url": {                                        "raw": "https://demo.convergepay.com/hosted-payments/transaction_token",                                      "protocol": "https",                                      "host": [                                              "demo",                                                "convergepay",                                                "com"                                      ],                                      "path": [                                                "hosted-payments",                                                "transaction_token"                                        ]                              }                        },                      "response": []                }        ],        "protocolProfileBehavior": {}}  Here is my code: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TfrmMain.GetElavonToken;var  xHTTP: TidHTTP;  xHandler: TIdSSLIOHandlerSocketOpenSSL;  xLogger: TIdLogDebug;     str_strm: TStringStream;  xRequestBody: TStringList;  idx: Integer;   https_post_cmd: String;    s: String;  snd_err: Boolean;begin  memSndRcv.Lines.Clear;   Screen.Cursor := crHourGlass;  Application.ProcessMessages;   //  https://demo.convergepay.com/hosted-payments/transaction_token  https_post_cmd := GV.Brook.Elavon.GetTokenURL;   xHTTP := nil;  xHandler := nil;  xLogger := nil;  xRequestBody := nil;   snd_err := False;  xml_mem_strm := nil;  str_strm := nil;   try     xHTTP := TIdHttp.Create(Self);    xHandler := TIdSSLIOHandlerSocketOpenSSL.Create(Self);    xLogger := TIdLogDebug.Create(Self);    xLogger.OnReceive := @logElvReceive;    xLogger.OnSend := @logElvSend;    xRequestBody := TStringList.Create;     xHTTP.IOHandler := xHandler;    xHandler.Intercept := xLogger;    xHandler.SSLOptions.Method := sslvTLSv1_2;     xHTTP.AllowCookies := True;    xHTTP.Request.BasicAuthentication := False;    xHTTP.Request.CustomHeaders.AddValue('Content-Type', 'application/x-www-form-urlencoded');    xHTTP.Request.CustomHeaders.AddValue('Accept', '*/*');    xHTTP.Request.CustomHeaders.AddValue('Accept-Encoding', 'gzip, deflate, br');    xHTTP.HTTPOptions := xHTTP.HTTPOptions + [hoForceEncodeParams, hoKeepOrigProtocol];    xHTTP.ProtocolVersion := pv1_1;     xRequestBody.Add('ssl_merchant_id= (withheld for security reasons)');    xRequestBody.Add('ssl_user_id=apiuser');    xRequestBody.Add('ssl_pin= (withheld for security reasons)');    xRequestBody.Add('ssl_transaction_type=ccsale');    xRequestBody.Add('ssl_amount=26.00');      memSndRcv.Lines.Add('Fetching Elavon token via HTTP');    Application.ProcessMessages;        str_strm := TStringStream.Create('');     try      xHTTP.Post(https_post_cmd, xRequestBody);    except      on E: Exception do        begin        snd_err := True;          memSndRcv.Lines.Add('Error on xHTTP.Post(' + GV.TxtMsg.https_get_cmd + ')');          memSndRcv.Lines.Add(E.Message);          Screen.Cursor := crDefault;        Application.ProcessMessages;          Exit;        end;    end;     xml_mem_strm.Position := 0;    memSndRcv.Lines.Add('Got it.');    Application.ProcessMessages;     idx := memSndRcv.Lines.Add('Loading XMLDoc...');    Application.ProcessMessages;    //ReadXMLFile(XMLDoc, xml_mem_strm);  memSndRcv.Lines[idx] := memSndRcv.Lines[idx] + 'Done.';    Application.ProcessMessages;   finally    xHTTP.Free;    xHandler.Free;     str_strm.Free;    xRequestBody.Free;     Screen.Cursor := crDefault;    Application.ProcessMessages;  end; end; ---------------------------------------------------------------------- engkin · 2021-05-21 18:45 I search for 'Protocol unknown' in Indy's source files, and I found: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   RSHTTPUnknownProtocol = 'Unknown Protocol'; I did another search for 'RSHTTPUnknownProtocol'. I found it in two places. This one seems related: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TIdCustomHTTP.PrepareRequest(ARequest: TIdHTTPRequest);...    if Length(LURI.Port) > 0 then begin      FURI.Port := LURI.Port;    end  else if TextIsSame(LURI.Protocol, 'http') then begin     {do not localize}      FURI.Port := IntToStr(IdPORT_HTTP);    end    else if TextIsSame(LURI.Protocol, 'https') then begin  {do not localize}      FURI.Port := IntToStr(IdPORT_https);    end    else if Length(FURI.Port) = 0 then begin      raise EIdUnknownProtocol.Create(RSHTTPUnknownProtocol);    end; There must be a port, or 'http' or 'https' otherwise some unknown protocol? ---------------------------------------------------------------------- Remy Lebeau · 2021-05-21 19:58 Quote from: RedOctober on May 21, 2021, 07:26:27 pmI'm getting a "Protocol unknown" error.  Can someone let me know what I am doing wrong? That error typically means you attempted to request a URL that does not begin with 'http:' or 'https:'.  Double-check that GV.Brook.Elavon.GetTokenURL returns a full URL. On a side note... Quote from: RedOctober on May 21, 2021, 07:26:27 pmCode: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i xHandler.SSLOptions.Method := sslvTLSv1_2; You should be using the SSLVersions property instead of the Method property: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i xHandler.SSLOptions.SSLVersions := [sslvTLSv1_2]; Quote from: RedOctober on May 21, 2021, 07:26:27 pmCode: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i xHTTP.Request.CustomHeaders.AddValue('Content-Type', 'application/x-www-form- urlencoded');xHTTP.Request.CustomHeaders.AddValue('Accept', '*/*');xHTTP.Request.CustomHeaders.AddValue('Accept-Encoding', 'gzip, deflate, br'); You should be using the Request's own sub-properties for those values, not the CustomHeaders property: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i xHTTP.Request.ContentType := 'application/x-www-form- urlencoded';xHTTP.Request.Accept := '*/*';xHTTP.Request.AcceptEncoding := 'gzip, deflate, br'; However, for the Content-Type header, the TStrings version of TIdHTTP.Post() will set that value for you, so you can safely omit it. But more importantly, you really should not be sending a custom Accept-Encoding header at all, unless you are actually prepared to handle those specific data types yourself manually should the server decide to send them (in which case, you should not be using TStringStream for that, not that it matters since you are not capturing the server's response body at all).  Indy does not implement any built-in support for 'br' at this time, and TIdHTTP's support for 'gzip' and 'deflate' is disabled by default, you have to assign a TIdZLibCompressorBase-derived component to the TIdHTTP.Compressor property, such as TIdCompressorZLib.  So, you should typically just let TIdHTTP handle the Accept-Encoding header for you, based on how TIdHTTP is actually configured. ---------------------------------------------------------------------- RedOctober · 2021-05-22 00:17 After making all the changes suggested, the code works now, and I can retrieve a token. Thanks all!