HTTP_URL_POST_STMF method help

Discussions related to HTTPAPI (An HTTP Client Package for RPG programming.) http://www.scottklement.com/httpapi/
Post Reply
jvondolteren
Posts: 6
Joined: Tue Mar 29, 2022 3:00 pm

HTTP_URL_POST_STMF method help

Post by jvondolteren »

We are attempting to call SIGNNOW API to upload a document with tags. We have been able to successfully test the API via POSTMAN API tester. However, when we attempt to call the API from within an RPGLE program using HTTPAPI, we are not successful and receive "CommTCP_read: Socket has been shut down" error. Unfortunately SIGNNOW's resources are unable to support us as we try to resolve this error; prior to yesterday we had been receiving a "502: Bad Gateway" error but that has since been resolved. From their perspective, if the API call works in POSTMAN then they have no further technical obligation.

I have included the small RPGLE test program, the HTTPAPI response ( I removed the encoded PDF ), and images of API set up in POSTMAN. I have also included code snippets in both HTTP and JQUERY from POSTMAN for the API. We are not sure what is causing the error and how to resolve it. If anyone has thoughts or ideas of what steps we might take next, we would be very grateful if you could share those with us. Also, please let us know if there is additional information we can provide.

Thank you,
Jim Von Dolteren

=============
RPGLE Source
=============

Code: Select all

**FREE

  ctl-opt dftactgrp(*NO) actgrp(*CALLER) bnddir('HTTPAPI');

  /copy qrpglesRC,httpapi_h
  /copy qrpglesRC,ifsio_h

  dcl-s contentType            char(64);
  dcl-s enc                 pointer;
  dcl-s pdf                 varchar(100);
  dcl-s msg                    char(52);
  dcl-s rc                      int(10);
  dcl-s tags                varchar(1000);
  dcl-s tempFile            varchar(200);

  pdf  = '/systemtemp/esign-test-document.pdf';
  tags = '[{"tag_name":"customer_name","role":"customer","label":"Your Name",'
       +   '"required":true,"type":"text","height":20,"width":200},'
       +  '{"tag_name":"customer_signature","role":"customer","label":"Customer Signature",'
       +   '"required":true,"type":"signature","height":20,"width":200},'
       +  '{"tag_name":"signature_date","role":"customer","label":"Signature Date",'
       +   '"required":true,"type":"text","height":20,"width":200,'
       +   '"validator_id":"059b068ef8ee5cc27e09ba79af58f9e805b7c2b3"}]' ;

  http_debug(*on);
  *inlr = *on;

  tempFile= http_tempfile();
  enc = http_mfd_encoder_open(tempFile: contentType);
  if (enc = *NULL);
    msg = http_error();
    dsply msg;
    return;
  endif;

  http_mfd_encoder_addvar( enc: 'Tags':  %addr(tags: *data): %len(tags));
  http_mfd_encoder_addstmf( enc: 'file': %trim(pdf): 'application/pdf');
  http_mfd_encoder_close(enc);

  http_xproc(HTTP_POINT_ADDL_HEADER: %paddr(addlHeaders)) ;
  rc = http_url_post_stmf( 'https://api.signnow.com/document/extractfield'
                         : tempFile
                         : '/tmp/http_result.txt'
                         : 30
                         : *omit
                         : 'multipart/form-data; boundary=TESTDOC202412130935');
  if (rc <> 1);
    msg = http_error();
    dsply msg;
    return;
  endif;

  exec sql call QSYS2.QCMDEXC('DSPF ''/tmp/http_result.txt''');
  unlink(tempFile);

  return;

  //____________________________________________________________________________
  //
  dcl-proc addlHeaders;
  //____________________________________________________________________________

  dcl-pi *N;
    headers                     varchar(32767);
  end-pi;

  dcl-s token                      char(1024);
  dcl-c crlf                      const(x'0d25');

  token    = '8c9198139c3f166a97d3b34b005770a5c6576d00b31f10906eda7cd8d6db4d91';
  headers = 'Authentication: Bearer ' + %trim(token) + crlf
          + 'Accept: application/json, application/pdf';

  end-proc;

Code: Select all

========================== 
HTTP API Response ( Edited )
==========================
HTTPAPI Ver 1.45 released 2021-09-20
NTLM Ver 1.4.0 released 2014-12-22
OS/400 Ver V7R5M0

http_url_post_stmf(): entered
getting post file size...
opening file to be sent...
opening file to be received
http_persist_open(): entered
http_long_ParseURL(): entered
DNS resolver retrans: 2
DNS resolver retry  : 2
DNS resolver options: x'00000136'
DNS default domain: HEARTLANDCOOP.COM
DNS server found: 10.1.244.1
DNS server found: 10.1.234.1
Nagle's algorithm (TCP_NODELAY) disabled.
SNI hostname set to: api.signnow.com
-------------------------------------------------------------------------------------
Dump of server-side certificate information:
-------------------------------------------------------------------------------------
Cert Validation Code = 6000
-----BEGIN CERTIFICATE-----
Removed for security purposes
-----END CERTIFICATE-----
Serial Number: 04:CA:69:36:71:03:85:4B:09:FD:B4:22:92:50:38:2E:B4:E4
Common Name: signnow.com
Issuer CN: E5
Issuer Country: US
Issuer Org: Let's Encrypt
Version: 3
not before: 20241118020805
Unknown Field: 02:08:05 18-11-2024
not after: 20250216020804
Unknown Field: 02:08:04 16-02-2025
pub key alg: 1.2.840.10045.2.1
signature algorithm: 1.2.840.10045.4.3.3
Unknown Field: 034200040AAF831EDCA30349AC5AF2041AAA0FCA6D5178D1F6D0486C1F45DDDF1BFEFAA335657870EF83B19EC995EFE4853EDB1971BCA5A2FF483606A060DB84D25F9076
Unknown Field: 256
Unknown Field: 1572CBB61C1F200BBF8A283C49664339
Unknown Field: 1.2.840.113549.2.5
Unknown Field: A6286960B88B85F4818F9B25025C3F4D648FDBEB
Unknown Field: EA588FC402A2280C487B6E8F2AB7D504B94B1F7A5E032644E6018CB99254E777
Unknown Field: 1
Unknown Field: signnow.com
Unknown Field: *.signnow.com
Unknown Field: 0
Unknown Field: 1.3.6.1.5.5.7.3.2
Unknown Field: 1.3.6.1.5.5.7.3.1
Unknown Field: 2.23.140.1.2.1
Unknown Field: http://e5.i.lencr.org/
Unknown Field: http://e5.o.lencr.org

Protocol Used: TLS Version 1.3
http_persist_post(): entered
http_persist_req(POST) entered.
http_long_ParseURL(): entered
http_long_ParseURL(): entered
do_oper(POST): entered
There are 0 cookies in the cache
POST /document/extractfield HTTP/1.1
Host: api.signnow.com
User-Agent: http-api/1.45
Content-Type: multipart/form-data; boundary=-httpapi-2024-12-13-13.04.04.776
Content-Length: 58257
Authentication: Bearer 8c9198139c3f166a97d3b34b005770a5c6576d00b31f10906eda7cd8d6db4d91
Accept: application/json, application/pdf

sendraw(): entered
---httpapi-2024-12-13-13.04.04.776
Content-Disposition: form-data; name="Tags"

[{"tag_name":"customer_name","role":"customer","label":"Your Name","required":true,"type":"text","height":20,"width":200},{"tag_name":"customer_signature","role":"customer","label":"Customer Signature","required":true,"type":"signature","height":20,"width":200},{"tag_name":"signature_date","role":"customer","label":"Signature Date","required":true,"type":"text","height":20,"width":200,"validator_id":"059b068ef8ee5cc27e09ba79af58f9e805b7c2b3"}]
---httpapi-2024-12-13-13.04.04.776
Content-Disposition: form-data; name="file"; filename="/systemtemp/esign-test-document.pdf"
Content-Type: application/pdf

%PDF-1.7
.
.
.
%%EOF
xref
0 0
trailer
<</Size 43/Root 1 0 R/Info 16 0 R/ID[<94CADEA69B40A44BAB87EFE73F83CB7C><94CADEA69B40A44BAB87EFE73F83CB7C>] /Prev 56327/XRefStm 55984>>
startxref
57344
%%EOF
---httpapi-2024-12-13-13.04.04.776--

recvresp(): entered
SetError() #44: CommTCP_read: Socket has been shut down.
recvresp(): end with err
http_close(): entered
===================
POSTMAN API Setup
===================
POSTMAN - SignNow API Setup - HEADERS.png
POSTMAN - SignNow API Setup - HEADERS.png (50.93 KiB) Viewed 26471 times
POSTMAN - SignNow API Setup - BODY.png
POSTMAN - SignNow API Setup - BODY.png (31.04 KiB) Viewed 26471 times
POSTMAN - SignNow API - Successful Response.png
POSTMAN - SignNow API - Successful Response.png (155.75 KiB) Viewed 26471 times
============================
POSTMAN - HTTP Code Snippet
============================
POST /document/fieldextract HTTP/1.1
Host: api.signnow.com
Authorization: Bearer 8c9198139c3f166a97d3b34b005770a5c6576d00b31f10906eda7cd8d6db4d91
Content-Length: 728
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW

------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="file"; filename="[PROXY]"
Content-Type: <Content-Type header here>

(data)
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="Tags"

[{"tag_name":"customer_name","role":"customer","label":"Your Name","required":true,"type":"text","height":20,"width":200},{"tag_name":"customer_signature","role":"customer","label":"Customer Signature","required":true,"type":"signature","height":20,"width":200},{"tag_name":"signature_date","role":"customer","label":"Signature Date","required":true,"type":"text","height":20,"width":200,"validator_id":"059b068ef8ee5cc27e09ba79af58f9e805b7c2b3"}]
------WebKitFormBoundary7MA4YWxkTrZu0gW--

==============================
POSTMAN - JQUERY Code Snippet
==============================
var form = new FormData();
form.append("file", fileInput.files[0], "");
form.append("Tags", "[{\"tag_name\":\"customer_name\",\"role\":\"customer\",\"label\":\"Your Name\",\"required\":true,\"type\":\"text\",\"height\":20,\"width\":200},{\"tag_name\":\"customer_signature\",\"role\":\"customer\",\"label\":\"Customer Signature\",\"required\":true,\"type\":\"signature\",\"height\":20,\"width\":200},{\"tag_name\":\"signature_date\",\"role\":\"customer\",\"label\":\"Signature Date\",\"required\":true,\"type\":\"text\",\"height\":20,\"width\":200,\"validator_id\":\"059b068ef8ee5cc27e09ba79af58f9e805b7c2b3\"}]");

var settings = {
"url": "https://api.signnow.com/document/fieldextract",
"method": "POST",
"timeout": 0,
"headers": {
"Authorization": "Bearer 8c9198139c3f166a97d3b34b005770a5c6576d00b31f10906eda7cd8d6db4d91"
},
"processData": false,
"mimeType": "multipart/form-data",
"contentType": false,
"data": form
};

$.ajax(settings).done(function (response) {
console.log(response);
});
Scott Klement
Site Admin
Posts: 872
Joined: Sun Jul 04, 2021 5:12 am

Re: HTTP_URL_POST_STMF method help

Post by Scott Klement »

Hello,

Looking over your program for obvious problems, I noticed this:
  1. http_mfd_encoder_open() calculates a content-type that it is expecting you to use. However, instead of using it you've simply hard-coded 'multipart/form-data; boundary=TESTDOC202412130935'; Instead of using that hard-coded string, please use the value provided in the contentType variable.
  2. You are missing the trailing CRLF in the addlHeaders() procedure.
That said, there is a LOT going on here, and it's too much for me to easily aborb and track everything in my head. I would normally write the program and then call/debug it to make sure all the problems are solved. So it's very possible that there are other (possibly many other) challenges aside from the obvious ones I noticed.

If you feel that you are over your head and are interested in hiring me to work through this with you, I'm happy to provide some professional services. Please let me know if that interests you.
jvondolteren
Posts: 6
Joined: Tue Mar 29, 2022 3:00 pm

Re: HTTP_URL_POST_STMF method help

Post by jvondolteren »

Scott, thank you for taking time to respond to my request for assistance. After correcting / adjusting program code as you suggested, I received the following error, "{"404":"Unable to find a route to match the URI: document\/extractfield"}". Funny enough, I ran the pgm a second time without making changes and am now getting a 400 Bad Request for, "{"error":"invalid_token","code":1537}". The plus here is that we are getting to the SIGNNOW server, the minus is dealing with this error of invalid token. As for "hiring" you to perhaps work with us, would you be able to correspond privately with me to discuss rates and expectations? My email address is jvondolteren@heartlandcoop.com.

Thank you.
emaxt6
Posts: 18
Joined: Mon Jun 05, 2023 4:02 pm

Re: HTTP_URL_POST_STMF method help

Post by emaxt6 »

You cannot expect to hard encode the token, those expire etc.
hence I think the error you get?
For those kind of APIs what I would suggest is, build a DS to contain the token, then a separate independent program to get the token.
Never build JSON "by hand", use the appropriate encoders (Scott ones are nice example), those can be source of errors and needless wasted time (the fact that XML and JSON can be opened with notepad is a curse :) interchange protocols were never meant to built using string concat :D).

Build a program X to interact with the particular API function.
Then build a separate test XT program to test X (that gets the DS token as a parameter).
Hardcode any string etc., test case in XT, not in X.
Post Reply