Getting HTTP 400 Bad Request Back from API Vendor with Bearer Key.

Discussions related to HTTPAPI (An HTTP Client Package for RPG programming.) http://www.scottklement.com/httpapi/
Post Reply
DaleSigwart
Posts: 6
Joined: Thu Dec 07, 2023 10:23 pm

Getting HTTP 400 Bad Request Back from API Vendor with Bearer Key.

Post by DaleSigwart »

Hi Scott and Community,

I am struggling with getting a JSON response from API vendor site that uses bearer token valuation using HTTPAPI

This is a three-step process.

Send HTTP Post JSON request with client credentials to retrieve bearer token. This is working.
Build the request header with the bearer token and transaction GUID
Send HTTP POST with JSON request payload to receive JSON response payload.

Step 1 build and Post JSON Token Request in RPG

URL = 'https://api-uat.sitename.com/token';

request = '{ "client_id" : ' + %trim(txclientid) + ', ' +
' "scopes" : ' + %trim(txScopes) + ' , ' +
' "grant_type" : "client_credentials" , +
"client_secret" : ' + %trim(txclentsec) + ' }' ;

rc = http_setAuth(HTTP_AUTH_NONE
: ' '
: ' ' );

rc = http_req( 'POST'
: URL
: '/home/dsigwart/respToken.json'
: *omit
: *omit
: request
: 'application/json');

// HTTP failures and communication failures
if rc <> 1;
msg = http_error();
dsply msg;
wkRspTmsp = %Timestamp;

Step 2 Build he request header with the bearer token and transaction GUID using HTTP_addtional headers
Step 3 Send HTTP POST with JSON request payload to receive JSON response. JSON response fails and instead I get ageneric HTTP 403 response from vendor cloud provider.

URL = 'https://api-uat.siteName.com/'calculate';

rc = http_xproc(HTTP_POINT_ADDL_HEADER:%paddr(add_Bearer_headers));
if rc <> 1;
msg = http_error();
dsply msg;
endif;

rc = http_req( 'POST'
: URL
: '/home/dsigwart/response.json'
: *omit
: '/home/dsigwart/handrequest.json'
: *omit
: 'application/vnd.tri.sitename.idt+json');

// HTTP failures and communication failures
if rc <> 1;
msg = http_error();
endif;


dcl-proc add_Bearer_Headers;
dcl-pi *n;
headers varchar(32767);
end-pi;
headers =
'Host: api-uat.siteName.com/calculate' + crlf +
'"Authorization" : "Bearer ' + %Trim(TokenDs.token) + '" ,'
+ crlf +
'"Content-Type" : "application/vnd.tri.sitename.idt+json",'
+ crlf +
'"Correlation-Id": "' + %trim(CORID) + '" , '
+ crlf +
'"Content-Length" : ' + %Char(prBuffLen) ;


I get the following errors back in the HTTP Log (note the log has been edited )

HTTPAPI Ver 1.45 released 2021-09-20
NTLM Ver 1.4.0 released 2014-12-22
OS/400 Ver V7R4M0

2023-12-07-11.38.49.099983: New iconv() objects set, PostRem=819. PostLoc=0. ProtRem=819. ProtLoc=0
2023-12-07-11.38.49.099918: https_init(): entered
2023-12-07-11.38.49.104852: QSSLPCL = *TLSV1 *TLSV1.1 *TLSV1.2
2023-12-07-11.38.49.104870: SSL version 2 support disabled
2023-12-07-11.38.49.104884: SSL version 3 support disabled
2023-12-07-11.38.49.104898: Old interface to TLS version 1.0 support disabled
2023-12-07-11.38.49.104913: TLS version 1.0 support disabled
2023-12-07-11.38.49.104927: TLS version 1.1 support disabled
2023-12-07-11.38.49.104940: TLS version 1.2 support enabled
2023-12-07-11.38.49.104953: TLS version 1.3 support disabled
2023-12-07-11.38.49.104965: initializing GSK environment
2023-12-07-11.38.49.105086: GSK Environment now available
2023-12-07-11.38.49.105099: -------------------------------------------------------------------------------------
2023-12-07-11.38.49.105110: Dump of local-side certificate information:
2023-12-07-11.38.49.105122: -------------------------------------------------------------------------------------
2023-12-07-11.38.49.105172: http_setauth(): entered
2023-12-07-11.38.49.106131: http_persist_open(): entered
2023-12-07-11.38.49.106161: http_long_ParseURL(): entered
2023-12-07-11.38.49.107125: DNS resolver retrans: 2
2023-12-07-11.38.49.107140: DNS resolver retry : 2
2023-12-07-11.38.49.107153: DNS resolver options: x'00000136'
2023-12-07-11.38.49.107515: DNS default domain: mySite.COM
2023-12-07-11.38.49.107532: DNS server found: 999.99.5.11
2023-12-07-11.38.49.107545: DNS server found: 999.99.5.12
2023-12-07-11.38.49.107563: Resolving host api-uat.sitename.com
2023-12-07-11.38.49.108173: inet_addr return value for this host is 4294967295
2023-12-07-11.38.49.235275: gethostbyname() returned 60932361
2023-12-07-11.38.49.235322: Looking up service https
2023-12-07-11.38.49.235364: Service table returns port 443
2023-12-07-11.38.49.235411: Nagle's algorithm (TCP_NODELAY) disabled.
2023-12-07-11.38.49.237367: SNI hostname set to: api-uat.sitename.com
2023-12-07-11.38.49.251054: -------------------------------------------------------------------------------------
2023-12-07-11.38.49.251073: Dump of server-side certificate information:
2023-12-07-11.38.49.251085: -------------------------------------------------------------------------------------
2023-12-07-11.38.49.251100: Cert Validation Code = 6000
2023-12-07-11.38.49.262203: -----BEGIN CERTIFICATE-----
MIIHBDCCBeygAwIBAgIQMrRvWm8KW2o7gecxNayjEjANBgkqhkiG9w0BAQsFADCB
ljELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G

LOjW0scsXQtkJ+b7vALkDQ9hNEBj5z5SWbrOKMyZ4vKk5uw7MyiIjqvG98sEohwL
gEzvEx63BvfS5O4cObkH2iWd3/8Vkgkc
2023-12-07-11.38.49.262814: -----END CERTIFICATE-----...

2023-12-07-11.38.49.263278: Protocol Used: TLS Version 1.2
2023-12-07-11.38.49.263303: http_persist_req(POST) entered.
2023-12-07-11.38.49.263329: http_long_ParseURL(): entered
2023-12-07-11.38.49.263375: http_long_ParseURL(): entered
2023-12-07-11.38.49.263415: do_oper(POST): entered
2023-12-07-11.38.49.263667: There are 0 cookies in the cache
2023-12-07-11.38.49.263700: CommSSL_BlockWrite(): gsk_secure_soc_write socket fd=2, flags=00000084, blocking=0
2023-12-07-11.38.49.263750: CommSSL_BlockWrite(): gsk_secure_soc_write rc=0, len=146
POST /oauth2/v1/token HTTP/1.1
Host: api-uat.onesourcetax.com
User-Agent: http-api/1.45
Content-Type: application/json
Content-Length: 196


2023-12-07-11.38.49.263770: senddoc(): entered
2023-12-07-11.38.49.263784: senddoc(): data left=196, chunk size=196, timeout=60, calling comm_blockWrite...
2023-12-07-11.38.49.263797: CommSSL_BlockWrite(): gsk_secure_soc_write socket fd=2, flags=00000084, blocking=0
2023-12-07-11.38.49.263830: CommSSL_BlockWrite(): gsk_secure_soc_write rc=0, len=196
{ "client_id" : "8EyUnaA3pEElY16XmIxY4MX3j25omIWB", "scopes" : "urn:tr:onesource:auth:api:IndirectTaxDetermination" , "grant_type" : "client_credentials" , "client_secret" : "zIJ1xeQfLyRKVwGR" }
2023-12-07-11.38.49.263848: senddoc(): comm_blockWrite returned 196
2023-12-07-11.38.49.263860: recvresp(): entered
2023-12-07-11.38.49.263876: recvresp: reading response header, space left=32767
HTTP/1.1 200 OK

2023-12-07-11.38.50.762446: recvresp: reading response header, space left=32750
Content-Type: application/json

2023-12-07-11.38.50.762489: recvresp: reading response header, space left=32718
Content-Length: 253

2023-12-07-11.38.50.762506: recvresp: reading response header, space left=32697
Connection: keep-alive

2023-12-07-11.38.50.762523: recvresp: reading response header, space left=32673
Date: Thu, 07 Dec 2023 17:38:50 GMT

...

2023-12-07-11.38.50.762927: recvresp: empty line, ending header, number of eol chars=2
2023-12-07-11.38.50.762948: recvresp: header resp code = 200 repeating=0
2023-12-07-11.38.50.762965: SetError() #13: HTTP/1.1 200 OK
2023-12-07-11.38.50.762978: recvresp(): end with 200
2023-12-07-11.38.50.763006: recvdoc parms: identity 253
2023-12-07-11.38.50.763077: header_load_cookies() entered
2023-12-07-11.38.50.763116: recvdoc(): entered
2023-12-07-11.38.50.763130: SetError() #0:
2023-12-07-11.38.50.763143: recvdoc(): Receiving 253 bytes.
{
"success": "approved",
"token": "fYxjMXpSROqmWAbSGNGALSXttiN3",
"access_token": "fYxjMXpSROqmWAbSGNGALSXttiN3",
"token_type": "Bearer",
"expires_in": "1799",
"issued_at": "1701970730713",
"client_id": "8EyUnaA3pEElY16XmIxY4MX3j25omIWB"
}
2023-12-07-11.38.50.764118: recvdoc(): have 253 of 253
2023-12-07-11.38.50.764186: http_close(): entered
HTTPAPI Ver 1.45 released 2021-09-20
NTLM Ver 1.4.0 released 2014-12-22
OS/400 Ver V7R4M0

2023-12-07-11.39.08.073997: http_persist_open(): entered
2023-12-07-11.39.08.075366: http_long_ParseURL(): entered
2023-12-07-11.39.08.075487: DNS resolver retrans: 2
2023-12-07-11.39.08.075512: DNS resolver retry : 2
2023-12-07-11.39.08.075535: DNS resolver options: x'00000136'
2023-12-07-11.39.08.075596: DNS default domain: mysite.COM
2023-12-07-11.39.08.075635: DNS server found: 999.99.5.11
2023-12-07-11.39.08.075670: DNS server found: 999.99.5.12
2023-12-07-11.39.08.075718: Resolving host api-uat.newsite.com
2023-12-07-11.39.08.075764: inet_addr return value for this host is 4294967295
2023-12-07-11.39.08.076231: gethostbyname() returned 60932381
2023-12-07-11.39.08.076270: Looking up service https
2023-12-07-11.39.08.076306: Service table returns port 443
2023-12-07-11.39.08.076371: Nagle's algorithm (TCP_NODELAY) disabled.
2023-12-07-11.39.08.077962: SNI hostname set to: api-uat.newsite.com
2023-12-07-11.39.08.091225: -------------------------------------------------------------------------------------
2023-12-07-11.39.08.091252: Dump of server-side certificate information:
2023-12-07-11.39.08.091273: -------------------------------------------------------------------------------------
2023-12-07-11.39.08.091299: Cert Validation Code = 6000
2023-12-07-11.39.08.167051: -----BEGIN CERTIFICATE-----
MIIHBDCCBeygAwIBAgIQMrRvWm8KW2o7gecxNayjEjANBgkqhkiG9w0BAQsFADCB
ljELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G

LOjW0scsXQtkJ+b7vALkDQ9hNEBj5z5SWbrOKMyZ4vKk5uw7MyiIjqvG98sEohwL
gEzvEx63BvfS5O4cObkH2iWd3/8Vkgkc
2023-12-07-11.39.08.167428: -----END CERTIFICATE-----

2023-12-07-11.39.08.168534: Protocol Used: TLS Version 1.2
2023-12-07-11.39.08.168578: http_persist_req(POST) entered.
2023-12-07-11.39.08.168622: http_long_ParseURL(): entered
2023-12-07-11.39.08.168683: http_long_ParseURL(): entered
2023-12-07-11.39.08.168726: do_oper(POST): entered
2023-12-07-11.39.08.168803: There are 0 cookies in the cache
2023-12-07-11.39.08.168860: CommSSL_BlockWrite(): gsk_secure_soc_write socket fd=3, flags=00000084, blocking=0
2023-12-07-11.39.08.168941: CommSSL_BlockWrite(): gsk_secure_soc_write rc=0, len=197
POST /indirect-tax-determination/taxes/v1/calculate HTTP/1.1
Host: api-uat.onesourcetax.com
User-Agent: http-api/1.45
Content-Type: application/vnd.tri.onesource.idt+json
Content-Length: 1245

2023-12-07-11.39.08.168991: CommSSL_BlockWrite(): gsk_secure_soc_write socket fd=3, flags=00000084, blocking=0
2023-12-07-11.39.08.169062: CommSSL_BlockWrite(): gsk_secure_soc_write rc=0, len=220
Host: api-uat.onesourcetax.com/indirect-tax-determination/taxes/v1/calculate
"Authorization" : "Bearer fYxjMXpSROqmWAbSGNGALSXttiN3","Content-Type" : "application/vnd.tri.onesource.idt+json","Correlation-Id": "DEV1"

2023-12-07-11.39.08.169109: CommSSL_BlockWrite(): gsk_secure_soc_write socket fd=3, flags=00000084, blocking=0
2023-12-07-11.39.08.169145: CommSSL_BlockWrite(): gsk_secure_soc_write rc=0, len=2


2023-12-07-11.39.08.169181: sendraw(): entered
2023-12-07-11.39.08.169205: sendraw(): data sent=0, chunk size=1245, calling Callback to get data...
2023-12-07-11.39.08.169238: sendraw(): data sent=0, chunk len=1245, timeout=60, calling comm_BlockWrite...
2023-12-07-11.39.08.169263: CommSSL_BlockWrite(): gsk_secure_soc_write socket fd=3, flags=00000084, blocking=0
2023-12-07-11.39.08.169348: CommSSL_BlockWrite(): gsk_secure_soc_write rc=0, len=1245
{
"companyRole" : "S",
"externalCompanyId" : "testcompany",
"processingOptions" : {
"chargeIncludedInAmounts" : false,
"chargeResponse" : "SeparateAuthority",
"repsonseSummary" : "FullDetails",
"documentAmountType" : "GrossAmount"
},
"documents" : [
{
"fiscalDate" : "2023-11-28",
"customerNumber" : "56789",
"currencyCode" : "USD",
"addresses" : [
{
"type" : "shipFrom",
"address1" : "450 S Valley Street",
"address2" : "",
"country" : "US",
"region" : "KS",
"city" : "Kansas City",
"postCode" : "66105",
"geoCode" : ""
},
{
"type" : "shipTo",
"address1" : "4747 Flora",
"address2" : "",
"country" : "US",
"region" : "MO",
"city" : "Kansas City",
"postCode" : "64110",
"geoCode" : ""
}
],
"documentDate": "2023-11-28",
"originalDocumentDate" : "2023-11-28",
"isCredit" : false,
"lines" : [
{
"lineNumber" : 1,
"amount" : "100.000000",
"quantities" : [
{
"amount" : 1,
"uom" : "Each"
}
],
"isCredit" : false,
"productCode" : "13",
"partNumber" : ""
}
]
}
]
}

2023-12-07-11.39.08.169381: sendraw(): comm_blockWrite returned 1245
2023-12-07-11.39.08.169405: recvresp(): entered
2023-12-07-11.39.08.169432: recvresp: reading response header, space left=32767
HTTP/1.1 400 Bad Request



2023-12-07-11.39.08.171138: recvresp: empty line, ending header, number of eol chars=2
2023-12-07-11.39.08.171179: recvresp: header resp code = 400 repeating=0
2023-12-07-11.39.08.171205: SetError() #13: HTTP/1.1 400 Bad Request
2023-12-07-11.39.08.171229: recvresp(): end with 400
2023-12-07-11.39.08.171271: recvdoc parms: identity 915
2023-12-07-11.39.08.171423: header_load_cookies() entered
2023-12-07-11.39.08.171477: recvdoc(): entered
2023-12-07-11.39.08.171503: SetError() #0:
2023-12-07-11.39.08.171527: recvdoc(): Receiving 915 bytes.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<HTML><HEAD><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<TITLE>ERROR: The request could not be satisfied</TITLE>
</HEAD><BODY>
<H1>400 ERROR</H1>
<H2>The request could not be satisfied.</H2>
<HR noshade size="1px">
Bad request.
We can't connect to the server for this app or website at this time. There might be too much traffic or a configuration error. Try again later, or contact the app or website owner.
<BR clear="all">
<BR clear="all">
<HR noshade size="1px">
<PRE>
Generated by
Request ID: J
</PRE>
<ADDRESS>
</ADDRESS>
</BODY></HTML>
2023-12-07-11.39.08.171575: recvdoc(): have 915 of 915
2023-12-07-11.39.08.171600: SetError() #13: HTTP/1.1 400 Bad Request
2023-12-07-11.39.08.171679: http_close(): entered


I have Validated the request JSON in at least 2 JSON validators.
I am not exactly sure hour the rc = http_xproc(HTTP_POINT_ADDL_HEADER:%paddr(add_Bearer_headers)) works but based on the httplog the headers seem to be accepted.

Not sure why I am getting the HTTP 400/ error.

Any help is appreciated.

Thanks,
Dale Sigwart
Scott Klement
Site Admin
Posts: 658
Joined: Sun Jul 04, 2021 5:12 am

Re: Getting HTTP 400 Bad Request Back from API Vendor with Bearer Key.

Post by Scott Klement »

You are not setting the headers correctly.
  1. You cannot set the Content-Type, Content-Length or Host headers this way. the HTTP_POINT_ADDL_HEADERS routine is only for "additional" headers, it can't be used for the ones that HTTPAPI sets for you. By coding those here, you are creating an invalid request.
  2. You have added a bunch of extra double quotes that aren't allowed per the HTTP protocol.
  3. You aren't terminating your headers correctly, but instead are separating them with commas.
This is what you probably meant to do:

Code: Select all

dcl-proc add_Bearer_Headers;
  dcl-pi *n;
    headers varchar(32767);
  end-pi;
  
  headers =
    'Authorization: Bearer ' + %Trim(TokenDs.token) + crlf
    'Correlation-Id: ' + %trim(CORID) + crlf;
    
end-proc;
DaleSigwart
Posts: 6
Joined: Thu Dec 07, 2023 10:23 pm

Re: Getting HTTP 400 Bad Request Back from API Vendor with Bearer Key.

Post by DaleSigwart »

Hi Scott,

That worked great! Thanks for your help.

Dale
Post Reply