Page 1 of 1
Receive & Transfer JSON Payload without any change
Posted: Tue Feb 18, 2025 9:20 pm
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.
Re: Receive & Transfer JSON Payload without any change
Posted: Wed Feb 19, 2025 12:51 am
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?
Re: Receive & Transfer JSON Payload without any change
Posted: Wed Feb 19, 2025 2:23 pm
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;
Re: Receive & Transfer JSON Payload without any change
Posted: Thu Feb 20, 2025 2:10 pm
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!
Re: Receive & Transfer JSON Payload without any change
Posted: Thu Feb 20, 2025 4:04 pm
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?
Re: Receive & Transfer JSON Payload without any change
Posted: Thu Feb 20, 2025 4:36 pm
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!
Re: Receive & Transfer JSON Payload without any change
Posted: Thu Feb 20, 2025 6:02 pm
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!
Re: Receive & Transfer JSON Payload without any change
Posted: Thu Feb 20, 2025 7:57 pm
by cooldude
Never mind Scott, used http_url_post and got it worked. Thanks for your inputs!
Re: Receive & Transfer JSON Payload without any change
Posted: Fri Feb 21, 2025 12:23 am
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.
Re: Receive & Transfer JSON Payload without any change
Posted: Fri Feb 21, 2025 2:54 pm
by cooldude
Sure Scott, will explore those options.
Thanks for your suggestions!