Receive & Transfer JSON Payload without any change

Discussions relating to the ScottKlement.com port of the open source YAJL JSON Reader/Generator. This includes the YAJL tool as well as the YAJLR4, YAJLGEN, YAJLINTO and YAJLDTAGEN add-ons from ScottKlement.com. http://www.scottklement.com/yajl/
Post Reply
cooldude
Posts: 15
Joined: Wed Feb 12, 2025 5:07 am

Receive & Transfer JSON Payload without any change

Post by cooldude »

Hi,
Having a situation to receive a JSON payload through an inbound API to IBMi and send the same (without any change) through an outbound API to a different system.

After receiving the JSON in a string (outbuf), can it be loaded to buffer to send it outbound, as shown below?

Code: Select all

yajl_genOpen(*On);
yajl_addChar(' ': %Trim(outBuf));
yajl_copyBuf( CCSID
: %addr(myJSON:*data)
: %len(myJSON)
: length );
%len(myJSON) = length;
yajl_saveBuf(%Trim(myJSONFile): errMsg);
yajl_genClose();

http_setCCSIDs( 1208: 0 );

// Also need code here to set up 'additional headers'
http_xproc( HTTP_POINT_ADDL_HEADER
          : %paddr(add_headers) );

rc = http_url_post( %Trim(GetProtocol(programName)) + '://' +
                    %Trim(GetHost(programName)) + ':' +
                    %Char(GetPort(programName)) +
                    %Trim(GetAPI(programName:'API'))
                  : %addr( myJSON : *data )
                  : %len( myJSON )
                  : %Trim(LogFile)
                  : HTTP_TIMEOUT
                  : HTTP_USERAGENT
                  : 'application/json; charset=UTF-8');
Kindly suggest if there is any other simple way to receive & transmit a payload through an SQLRPGLE program.
Let me know if further details are required.

Thanks,
Prakash.
Scott Klement
Site Admin
Posts: 872
Joined: Sun Jul 04, 2021 5:12 am

Re: Receive & Transfer JSON Payload without any change

Post by Scott Klement »

You say you're receiving a JSON payload through an inbound API. But, your code isn't doing that, instead its simply creating a fresh JSON document .

Then what? You want to send it out.. but your code is making a call to a URL, no tsending data ot....?

Do I even understand what you are interested in?
cooldude
Posts: 15
Joined: Wed Feb 12, 2025 5:07 am

Re: Receive & Transfer JSON Payload without any change

Post by cooldude »

Thanks for your response Scott.
Mentioned only outbound, because Inbound code already was working for a different project.
From the payload received from inbound, trying to create same new payload to send to outbound.
Have not tested the outbound yet and planning to do it today.
Would like to know if this is the right approach, or something better or simpler can be done for this scenario.
Was also exploring below SQL command to send the payload outbound:
Exec SQL values QSYS2.HTTP_POST(:url, :request, :options) into :response;

Please advise and let me know if you need further information.

Here is the inbound process:

Process module:

Code: Select all

  //Receive input payload
  If GetInput( Method: ErrMsg ) = False;
      // some code to check for any error message
      LeaveSr;
  EndIf;

  If Method <> 'POST';
     // some code to check for any error message  
    LeaveSr;
  Else;
    If GetJSONDocument( OrderDS : DocNode);
      // some code to send response and handle error
      ExSr ResponseRoutine;
      yajl_tree_free(DocNode);
    Else;
      // some code to check for any error message
    EndIf;
  EndIf; 

BegSr ResponseRoutine;
  yajl_genOpen(*On);
  yajl_beginObj();
  yajl_beginObj('order');
    yajl_addNum('orderNumber': %Char(OrderDS.number));
  yajl_endObj();
  yajl_addChar('success': 'true');
  yajl_endObj();
  SendResponse(OrderDS);
  yajl_genClose();
EndSr;

Procedures invoked:
Dcl-Proc getInput;
  Dcl-PI *n ind;
    method varchar(10);
    errmsg varchar(500);
  End-PI;
  Dcl-PR getenv pointer extproc(*dclcase);
    var pointer value options(*string);
  End-PR;
  Dcl-S env pointer;
  Dcl-S pos int(10);
  Dcl-S url varchar(1000);

  errMsg = '';
  method = 'GET';
  url    = '';

  // ------------------------------------------------------
  // Retrieve the HTTP method.
  //  -  Default to GET if not provided
  // ------------------------------------------------------

  env = getenv('REQUEST_METHOD');
  if env <> *null;
    method = %xlate(lower: UPPER: %str(env));
  endif;

  // ------------------------------------------------------
  //  Retrieve the URL
  //   - Should always be provided!
  // ------------------------------------------------------

  env = getenv('REQUEST_URI');
  if env = *null;
    errMsg = 'Unable to retrieve URL';
    return *off;
  else;
    url = %xlate(UPPER: lower: %str(env));
  endif;

  return *on;
End-Proc;

Dcl-Proc GetJSONDocument;
  Dcl-PI *N Ind;
    OrderDS LikeDS(OrderDS_T);
    DocNode Like(yajl_val);
  End-PI;

  Dcl-DS ErrorCode;
    *n int(10) inz(0);
    *n int(10) inz(0);
  End-DS;

  Dcl-PR getenv pointer extproc(*dclcase);
    var pointer value options(*string);
  End-PR;

  //Dcl-S contentLength Int(10); //Moved definition to be at program level
  Dcl-S fd        Int(10);
  Dcl-S inpBuf    Pointer;
  Dcl-S inpLength Int(10);
  //Dcl-S outBuf    Char(65535) Based(p);  //Moved definition to be at program level
  Dcl-S outString Char(500) Inz;
  //Dcl-S p         Pointer;  //Moved definition to be at program level

  Dcl-C CR x'25';
  Dcl-C CRLF x'0d25';
  Dcl-C LF x'0D';
  Dcl-C O_WRONLY 2;
  Dcl-C O_TEXTDATA 16777216;

  //Clear outString;
  DocNode = yajl_stdin_load_tree(*On: ErrMsg);

  If ErrMsg <> '';
    OrderDS.HttpStatus = 500;
    OrderDS.ErrorMsg = 'json parse: ' + errMsg;
    OrderDS.Success = *off;
  EndIf;

  If HTTPDebug = True Or OrderDS.ErrorMsg <> *Blanks;
    Pathname = %trim(Folderpathin);

    InpFileName = %Trim(programName) + '_' + %Char(JobNbr) + '_' +
               %Char(%Timestamp()) + '.txt';

    ContentLength = *Zeros;
    p = getenv('CONTENT_LENGTH');
    If p <> *null;
      ContentLength = %Int(%Str(p));
    EndIf;
    If ContentLength > 0;
      ReadIn( %Addr(inpBuf)
           : ContentLength
           : inpLength
           : errorCode);
     CmdString = 'STRQSH CMD(' + Q + 'touch -C 1252 ' +
               %Trim(Pathname) + '/' + %Trim(InpFileName) + Q + ')';
     CmdLength = %Len(%Trim(CmdString));
     Monitor;
       RunCommand(CmdString: CmdLength);
     On-Error;
     EndMon;

     fd = Open(%Trim(Pathname) + '/' + %Trim(InpFileName): O_WRONLY+O_TEXTDATA);
     If fd >= 0;
       monitor;
         ContentLength = yajl_stringify( DocNode
                                     : p
                                     : %Size(outBuf));
         WriteOut(fd: %Trim(outBuf): ContentLength);
       on-error;
       endmon;

       CloseF(fd);
     EndIf;
   EndIf;
 EndIf;
 Return OrderDS.Success;
End-Proc;

Dcl-Proc sendResponse;
 Dcl-PI *n ind;
   OrderDS likeds(OrderDS_t) const;
 End-PI;
 Dcl-S errMsg VarChar(500) Inz('');

 errMsg = OrderDS.errorMsg;
 yajl_writeStdout(OrderDS.httpStatus: errMsg);
 return *On;
End-Proc;
cooldude
Posts: 15
Joined: Wed Feb 12, 2025 5:07 am

Re: Receive & Transfer JSON Payload without any change

Post by cooldude »

After doing some testing, would like to know if there is a way to copy the string (outbuf = payload received) into buffer or sending the string directly to target is the only way? Please advise.

Thanks!
Scott Klement
Site Admin
Posts: 872
Joined: Sun Jul 04, 2021 5:12 am

Re: Receive & Transfer JSON Payload without any change

Post by Scott Klement »

It looks to me like you are already receiving data into a variable in your program. I don't understand what problem you're having.

The code is very confused. It seems to read the data into a variable, but then never uses the variable it read into, instead using yajl_stringify() to re-generate the data. So you are doing the work twice, and only using the second result.

But at any rate you have your data in a variable, and then you can pass that variable to the output routine. So... what problem are you having?
cooldude
Posts: 15
Joined: Wed Feb 12, 2025 5:07 am

Re: Receive & Transfer JSON Payload without any change

Post by cooldude »

Yes Scott, got the payload in a string.

Now I would like to send this string (which consists of JSON payload to be sent out) to outside world (URL endpoint) and save it in a file in IFS. Which YAJL API is more effective to do this transfer? Please suggest.

Thanks!
cooldude
Posts: 15
Joined: Wed Feb 12, 2025 5:07 am

Re: Receive & Transfer JSON Payload without any change

Post by cooldude »

Scott,
Tried to use http_string, but it resulted 500 error. Could be because no option to add headers with credentials (Client id, Client secret).
http_string( Method: url: OutBuf : 'application/json' );

Thanks!
cooldude
Posts: 15
Joined: Wed Feb 12, 2025 5:07 am

Re: Receive & Transfer JSON Payload without any change

Post by cooldude »

Never mind Scott, used http_url_post and got it worked. Thanks for your inputs!
Scott Klement
Site Admin
Posts: 872
Joined: Sun Jul 04, 2021 5:12 am

Re: Receive & Transfer JSON Payload without any change

Post by Scott Klement »

Hmmm.. okay. So YAJL is for interpreting or creating JSON. It does have routines for transferring data.

You can use HTTPAPI for that if you want to transfer it via HTTP. I'd suggest either the http_req() or http_string().

Or you can use another tool such as the SQL HTTP routines, etc.
cooldude
Posts: 15
Joined: Wed Feb 12, 2025 5:07 am

Re: Receive & Transfer JSON Payload without any change

Post by cooldude »

Sure Scott, will explore those options.
Thanks for your suggestions!
Post Reply