Call to REST API Endpoint Generates Error 9318 (Using OpenEdge.Net.pl) Code Supplied in Body - Forum - OpenEdge Development - Progress Community

Call to REST API Endpoint Generates Error 9318 (Using OpenEdge.Net.pl) Code Supplied in Body

 Forum

Call to REST API Endpoint Generates Error 9318 (Using OpenEdge.Net.pl) Code Supplied in Body

This question is answered

Hello, All:

This one is most likely a Cert issue but I need to be sure before I go down that rabbit hole. 

I am using this program (code below) and hitting an Avatax endpoint - query filter is still a TBD, but I am stuck on getting connected to the endpoint using OpenEdge.Net.pl:I am using a tweaked sample I got from a Peter Judge post on the OpenEdge Knowledgebase. 

Attached is the output image, too. 

Any help is much appreciated, as always.

CODE BEGINS HERE

______________________________
block-level on error undo, throw.

using OpenEdge.Net.HTTP.*.

using OpenEdge.Net.URI.

using OpenEdge.Net.UriSchemeEnum.

using Progress.Json.ObjectModel.JsonObject.

USING OpenEdge.Net.HTTP.Lib.ClientLibraryBuilder.

/* *************************** Main Block *************************** */
define variable oClient as IHttpClient no-undo.
define variable oUri as URI no-undo.
define variable oReq as IHttpRequest no-undo.
define variable oResp as IHttpResponse no-undo.
define variable oCreds as Credentials no-undo.
define variable oJson as JsonObject no-undo.

DEFINE VARIABLE oLib AS IHttpClientLibrary NO-UNDO.

oLib = ClientLibraryBuilder:Build()
:sslVerifyHost(NO)
:Library.

oClient = ClientBuilder:Build()
:UsingLibrary(oLib)
:Client.

oCreds = new Credentials('application', 'dummyusername', 'dummypassword').

oUri = new URI('https', 'sandbox-rest.avatax.com').
oUri:Path = '/api/v2/taxrates/bypostalcode'.

oReq = RequestBuilder:Build('GET', oUri)
:UsingBasicAuthentication(oCreds)
:AcceptJson()
:Request.

oResp = ResponseBuilder:Build():Response.
oClient:Execute(oReq, oResp).

MESSAGE oResp:StatusCode
VIEW-AS ALERT-BOX.

if type-of(oResp:Entity, JsonObject) then
assign oJson = cast(oResp:Entity, JsonObject).

/* do what you need to with the JSON here */

catch oError as Progress.Lang.Error :
message
oError:GetMessage(1) skip(2)
oError:CallStack
view-as alert-box.
end catch.

Verified Answer
  • So, after some research it turned out it was a Cert problem.

    I followed the remedy described in this KB entry, in case anyone's interested:

    knowledgebase.progress.com/.../P183764

    Links die, so I am pasting the remedy here:

    HOW TO USE GET METHOD IN HTTP REQUEST USING SSL  WITH SOCKET CONNECTION FROM ABL?

    Printable View

    INFORMATION

    Article Number 000017681

    Environment Product: OpenEdge

    Version: 10.x, 11.x

    OS: Windows

    Other: N/A

    Question/Problem Description

    How to use GET method in HTTP request using SSL  with socket connection from ABL?

    How to use SSL socket connection to HTTP request using ABL?

    How to use secure socket layer socket to HTTP request using ABL?

    Steps to Reproduce

    Clarifying Information

    Error Message

    Defect/Enhancement Number

    Cause

    Resolution

    In order for you to use SSL to submit HTTP request using ABL socket connection, you need to first copy the Site's root SSL certificate from internet browser to your local machine where ABL or AppServer/webspeed will run.  Then you need to using DLC/bin/pkiutil.bat to import the SSL certificate to DLC/certs folder.

    The steps to do it is demonstrate below using Internet Explorer (IE):

    1.  Connect to the https site using the IE

    2. Click on the lock icon that is right after the Address bar before the refresh button (if you mouse over the lock it will read "Security Report") > View Certificates.

    3. Click on the "Certificate Path" tab and select to root certificate issuer, that is the very top certificate instead of site certificate > Click on "View Certificate" button

    4. Click on the "Detail" tab and click on the "Copy to File" button which will give you a wizard to click next.

    5. Choose the "Base-64 encoded X.509(.CER)" format radio button > Click Next > Browse to a directory that you can easily find the saved certificate.  I recommend you to place it on the OpenEdge working directory > give it a name, for instance, socket and click OK > Click Next > Click Finish to save the file.  It will save the file named as socket.cer.

    Importing the socket.cer using mkhashfile at the proenv prompt:

    1. Click Start on the desktop > All Programs > OpenEdge > proenv

    2. On the proenv prompt type the following:

    proenv>mkhashfile socket.cer

    3. You will see this output:

    OpenEdge Release 10.2B0109  as of Wed Jul 21 09:04:05 EDT 2010

    Running SSLC command ...

    Copying socket.cer and 594f1775.0 to C:\Progress\OE\102b\dlc\certs

    proenv>

    The above command will import a certificate to the %DLC%\certs file.  Now this file can be distributed to all the OpenEdge install machine that will use the SSL socket connection using ABL.

    Copy the following ABL code and save it as ssl_socket.p.  You need to replace the URL and the GET parameters to send with HTTPS request in the place of <>.

    /**************************************Start ssl_socket.p****************************************/

    DEFINE VARIABLE vcWebResp    AS CHARACTER        NO-UNDO.

    DEFINE VARIABLE lSucess      AS LOGICAL          NO-UNDO.

    DEFINE VARIABLE mResponse    AS MEMPTR           NO-UNDO.

    DEFINE VARIABLE mRequest       AS MEMPTR.

    DEFINE VARIABLE postUrl AS CHAR.

    DEFINE VARIABLE vcRequest as char format "x(100)" no-undo.

    DEFINE VARIABLE postData  as char format "x(100)" no-undo.

    DEFINE VARIABLE vhSocket   AS HANDLE                                NO-UNDO.

    CREATE SOCKET vhSocket.

    /**********Using Windows API****************/

    PROCEDURE Sleep EXTERNAL "KERNEL32.DLL":

    DEFINE INPUT PARAMETER intMilliseconds AS LONG.

    END PROCEDURE.

    vhSocket:CONNECT("-H <Server_Name.  which is found after https://> -S 443 -ssl -nohostverify") NO-ERROR.

    IF vhSocket:CONNECTED() = FALSE THEN

    do:

    message "Error".

    MESSAGE ERROR-STATUS:GET-MESSAGE(1) VIEW-AS ALERT-BOX.

    end.

    else

    message "Connected".

    pause.

    hide message no-pause.

    message "GET".

    postUrl = "/complete_path_includin.g_file_name as seen in the URL>".

    postData = "<?parameters as seen on the URL>".

    vcRequest = 'GET ' +

                postUrl +

                postData +

                " HTTP/1.0 ~r~n" +

                "Host: secure2.nmi.com" +

                "~r~nUser-Agent: " +

                "~r~nConnection: close~r~n~r~n"

                .

       SET-SIZE(mRequest)            = 0.

       SET-SIZE(mRequest)            = LENGTH(vcRequest) + 1.

       SET-BYTE-ORDER(mRequest)      = BIG-ENDIAN.

       PUT-STRING(mRequest,1)        = vcRequest .

    vhSocket:WRITE(mRequest, 1, LENGTH(vcRequest)).

    hide message no-pause.

    message "WRITE message complete".

    RUN Sleep (5000). /* 5 seconds */

    DO WHILE vhSocket:GET-BYTES-AVAILABLE() > 0:

            SET-SIZE(mResponse) = vhSocket:GET-BYTES-AVAILABLE() + 1.

            SET-BYTE-ORDER(mResponse) = BIG-ENDIAN.

            vhSocket:READ(mResponse,1,1,vhSocket:GET-BYTES-AVAILABLE()).

            vcWebResp = vcWebResp + GET-STRING(mResponse,1).

    END.

    hide message no-pause.

    message "READ Response complete".

    pause.

    hide message no-pause.

    message "Response: " + vcWebResp

       VIEW-AS ALERT-BOX.

    pause.

    vhSocket:DISCONNECT().

    DELETE OBJECT vhSocket.

    message "END".

    pause.

    /**************************************End ssl_socket.p****************************************/

    Run the above program to get the response back from the https connection.  If the response takes longer time, you can increase the "RUN Sleep time to more than 5 seconds.  Usually 5 seconds is enough.

All Replies
  • Very very like a certificate problem.

    https://knowledgebase.progress.com/articles/Article/P136334

  • This one might be a bit more suitable

    knowledgebase.progress.com/.../P136334

  • Very likely a certificate problem, see:

    knowledgebase.progress.com/.../P136334

  • So, after some research it turned out it was a Cert problem.

    I followed the remedy described in this KB entry, in case anyone's interested:

    knowledgebase.progress.com/.../P183764

    Links die, so I am pasting the remedy here:

    HOW TO USE GET METHOD IN HTTP REQUEST USING SSL  WITH SOCKET CONNECTION FROM ABL?

    Printable View

    INFORMATION

    Article Number 000017681

    Environment Product: OpenEdge

    Version: 10.x, 11.x

    OS: Windows

    Other: N/A

    Question/Problem Description

    How to use GET method in HTTP request using SSL  with socket connection from ABL?

    How to use SSL socket connection to HTTP request using ABL?

    How to use secure socket layer socket to HTTP request using ABL?

    Steps to Reproduce

    Clarifying Information

    Error Message

    Defect/Enhancement Number

    Cause

    Resolution

    In order for you to use SSL to submit HTTP request using ABL socket connection, you need to first copy the Site's root SSL certificate from internet browser to your local machine where ABL or AppServer/webspeed will run.  Then you need to using DLC/bin/pkiutil.bat to import the SSL certificate to DLC/certs folder.

    The steps to do it is demonstrate below using Internet Explorer (IE):

    1.  Connect to the https site using the IE

    2. Click on the lock icon that is right after the Address bar before the refresh button (if you mouse over the lock it will read "Security Report") > View Certificates.

    3. Click on the "Certificate Path" tab and select to root certificate issuer, that is the very top certificate instead of site certificate > Click on "View Certificate" button

    4. Click on the "Detail" tab and click on the "Copy to File" button which will give you a wizard to click next.

    5. Choose the "Base-64 encoded X.509(.CER)" format radio button > Click Next > Browse to a directory that you can easily find the saved certificate.  I recommend you to place it on the OpenEdge working directory > give it a name, for instance, socket and click OK > Click Next > Click Finish to save the file.  It will save the file named as socket.cer.

    Importing the socket.cer using mkhashfile at the proenv prompt:

    1. Click Start on the desktop > All Programs > OpenEdge > proenv

    2. On the proenv prompt type the following:

    proenv>mkhashfile socket.cer

    3. You will see this output:

    OpenEdge Release 10.2B0109  as of Wed Jul 21 09:04:05 EDT 2010

    Running SSLC command ...

    Copying socket.cer and 594f1775.0 to C:\Progress\OE\102b\dlc\certs

    proenv>

    The above command will import a certificate to the %DLC%\certs file.  Now this file can be distributed to all the OpenEdge install machine that will use the SSL socket connection using ABL.

    Copy the following ABL code and save it as ssl_socket.p.  You need to replace the URL and the GET parameters to send with HTTPS request in the place of <>.

    /**************************************Start ssl_socket.p****************************************/

    DEFINE VARIABLE vcWebResp    AS CHARACTER        NO-UNDO.

    DEFINE VARIABLE lSucess      AS LOGICAL          NO-UNDO.

    DEFINE VARIABLE mResponse    AS MEMPTR           NO-UNDO.

    DEFINE VARIABLE mRequest       AS MEMPTR.

    DEFINE VARIABLE postUrl AS CHAR.

    DEFINE VARIABLE vcRequest as char format "x(100)" no-undo.

    DEFINE VARIABLE postData  as char format "x(100)" no-undo.

    DEFINE VARIABLE vhSocket   AS HANDLE                                NO-UNDO.

    CREATE SOCKET vhSocket.

    /**********Using Windows API****************/

    PROCEDURE Sleep EXTERNAL "KERNEL32.DLL":

    DEFINE INPUT PARAMETER intMilliseconds AS LONG.

    END PROCEDURE.

    vhSocket:CONNECT("-H <Server_Name.  which is found after https://> -S 443 -ssl -nohostverify") NO-ERROR.

    IF vhSocket:CONNECTED() = FALSE THEN

    do:

    message "Error".

    MESSAGE ERROR-STATUS:GET-MESSAGE(1) VIEW-AS ALERT-BOX.

    end.

    else

    message "Connected".

    pause.

    hide message no-pause.

    message "GET".

    postUrl = "/complete_path_includin.g_file_name as seen in the URL>".

    postData = "<?parameters as seen on the URL>".

    vcRequest = 'GET ' +

                postUrl +

                postData +

                " HTTP/1.0 ~r~n" +

                "Host: secure2.nmi.com" +

                "~r~nUser-Agent: " +

                "~r~nConnection: close~r~n~r~n"

                .

       SET-SIZE(mRequest)            = 0.

       SET-SIZE(mRequest)            = LENGTH(vcRequest) + 1.

       SET-BYTE-ORDER(mRequest)      = BIG-ENDIAN.

       PUT-STRING(mRequest,1)        = vcRequest .

    vhSocket:WRITE(mRequest, 1, LENGTH(vcRequest)).

    hide message no-pause.

    message "WRITE message complete".

    RUN Sleep (5000). /* 5 seconds */

    DO WHILE vhSocket:GET-BYTES-AVAILABLE() > 0:

            SET-SIZE(mResponse) = vhSocket:GET-BYTES-AVAILABLE() + 1.

            SET-BYTE-ORDER(mResponse) = BIG-ENDIAN.

            vhSocket:READ(mResponse,1,1,vhSocket:GET-BYTES-AVAILABLE()).

            vcWebResp = vcWebResp + GET-STRING(mResponse,1).

    END.

    hide message no-pause.

    message "READ Response complete".

    pause.

    hide message no-pause.

    message "Response: " + vcWebResp

       VIEW-AS ALERT-BOX.

    pause.

    vhSocket:DISCONNECT().

    DELETE OBJECT vhSocket.

    message "END".

    pause.

    /**************************************End ssl_socket.p****************************************/

    Run the above program to get the response back from the https connection.  If the response takes longer time, you can increase the "RUN Sleep time to more than 5 seconds.  Usually 5 seconds is enough.