Original Message:
Sent: Wed July 17, 2024 09:17 AM
From: Celian Toureille
Subject: strange issue with openapi3 and context.get('request.body')
Hi Steve,
Could you provide some exemple of readAsJSON being used inside on a gateway script with a Javascript promise ?
I might be missing some knowlegde to make things work properly.
------------------------------
Celian Toureille
Original Message:
Sent: Mon July 15, 2024 09:19 AM
From: Steve Linn
Subject: strange issue with openapi3 and context.get('request.body')
Hi Celian,
For sure asynchronous callbacks will make the code more complicated. Its pretty common though to for asynchronous functions to use callback functions where in your example, you'd pass the JSON from the first readAs function (for your example you could be using the readAsJSON function) to a callback function, which would do its own readAs and then pass the original JSON and its own readAs JSON to the next callback, and the final readAs function would then have all three available to it to aggregate the three results. There is also JavaScript promises that would allow you to have the code look more "synchronous" where you'd await for the first readAs to complete before doing the next, etc.
I'm not sure what you mean by "Not being to assign the response in a JSON format inside a variable is unpractical." If you are using readAsBuffer, then you'll need to do a JSON.parse on that returned buffer, whereas readAsJSON will do the parse for you. As for "Invokes should have a parameter to set if you want the result entirely loaded in a JSON/XML format or not." that is the purpose of the parse policy. The v5(c) Gateway would always implicitly parse the invoke response based upon the response content type header that was returned, but this received many complaints as many didn't want the response parsed at all, or in some cases they wanted to parse the response with different parser limits and they didn't want to have a one size fits all parser limits for all APIs, which is why the design decision was made for the v10 API Gateway to do no implicit parsing, leaving the data in context as a Buffer. However, the readAsJSON for example will do that parsing for you, or you could do a readAsBuffer and then do a JSON.parse. The option of how to do it is left to you to handle the response as you wish.
Hope this helps!
Regards,
Steve
------------------------------
Steve Linn
Senior Consulting I/T Specialist
IBM
Original Message:
Sent: Mon July 15, 2024 03:29 AM
From: Celian Toureille
Subject: strange issue with openapi3 and context.get('request.body')
Hi Steve,
The main trouble using context.<messagename>.body.readAsXXXX(function(error,thing){}) was that it complicates a lot the code. If you have 2 or 3 invokes response you need to use in a gateway script it quickly becomes a mess. Especially if you using one readAs inside an other readAs. Not being to assign the response in a JSON format inside a variable is unpractical.
Using Parse policies works but adds a lot of blocs on my API transformations so I don't like them. Invokes should have a parameter to set if you want the result entirely loaded in a JSON/XML format or not.
I almost always make some good error handling after my invokes with meaningful logging. Buffer objects are a like a pain in the back.
I will take in account your advise on big documents sizes to parse, it seems a good use case for a parse policy.
------------------------------
Celian Toureille
Original Message:
Sent: Fri July 12, 2024 05:05 PM
From: Steve Linn
Subject: strange issue with openapi3 and context.get('request.body')
Hi Celian,
Just a few comments :-) . Those parse policies you don't apparently like have the side benefit if the invoke response is being streamed of reading the stream to completion and updating the context so your context.get have the body data instead of `null`. You apparently have a use case where the invoke response was not being streamed so the context.get had the body present. If you don't like the parse policies, you can also use the context.<messagename>.body.readAsXXXX functions which would also read the data off of the stream (or directly from the context if the data is already buffered) and you can be assured that you'll always get your data regardless of the streaming status. You're doing your own JSON.parse in your GatewayScript, but also note that if you have some special parsing requirements, perhaps a very large response document, that the parse policy will allow you to specify custom parsing limits where as the JSON.parse will not.
As for Buffer, Buffers, etc, that's all part of the JavaScript language that GatewayScript is built on top of. In general you should use the Buffer class although there are some instances of large data, which I personally have not run into, where the Buffers would be more suitable.
Best Regards,
Steve Linn
------------------------------
Steve Linn
Senior Consulting I/T Specialist
IBM
Original Message:
Sent: Wed July 10, 2024 05:32 AM
From: Celian Toureille
Subject: strange issue with openapi3 and context.get('request.body')
Hi everyone. I finally found a way to read an invoke response properly inside a GatewayScript.
My Invoke returns it's results inside the variable named invokeResult.
Inside my gateway script I put the following code :
let invokeResult = context.get('invokeResult');let invokeResultBody = JSON.parse(invokeResult.body.toString());
I can now use the result body as I want !!! No need for stupid parse blocs anymore.
It was really awful to found since the document is really messed up.
We have the Buffer class, the Buffers class, the Buf class, the Bufs class.... Why can't you have one buffer class, and one buf class...
In hope it help someone in the futur,
Celian
------------------------------
Celian Toureille
Original Message:
Sent: Thu October 12, 2023 02:44 PM
From: Steve Linn
Subject: strange issue with openapi3 and context.get('request.body')
- Hi Rajesh,
In v5 and thus v5 compatible gateways, payloads posted to the API were always buffered before the API assembly started processing, thus the apim.getvariable('request'), the request.body would be always be present for a POST or PUT request. In the v10/API Gateway, the gateway will not buffer request payloads by default. Instead it will allow the request.body to stream into the Gateway while the assembly starts processing, thus request.body isn't available when your GatewayScript that does the context.get begins to execute. It is a performance benefit to stream the request until the data is actually needed, but if you want to see what is in that request, you'll need to stop streaming since you're wanting to see the data at that point. The context.get function is not sufficient to stop streaming.
To stop the streaming of the request there are a few ways:
1. The simplest way to get request.body populated is to have as your first policy, or at least a policy prior to when you want to see request.body, be a parse policy. This policy will read the entire request payload from the stream and depending upon the parse policy options will parse the payload into an XML document or JSON object for example. The result of the parse will be written by default to message.body although you could have it written to any context message you wish, for example, mymessage, which would parse the data to mymessage.body.
2. Another option to force buffering is to set x-ibm-configuration.buffering to a boolean true. There is an open product issue in the UI presently where this property isn't shown in the UI, so for now you'd need to add this property manually in the source view of the API.
3. In a GatewayScript policy, you can issue a context.request.body.readAs[Buffer|JSON|XML] function. In the asynchronous callback argument to this function, the buffer|object|document will be provided to you in your processing. This function, like the parse policy, will read the data from the stream until the stream has been fully read.
Best Regards,
Steve
------------------------------
Steve Linn
Senior Consulting I/T Specialist
IBM
Original Message:
Sent: Wed October 11, 2023 01:11 AM
From: Rajesh Solanki
Subject: strange issue with openapi3 and context.get('request.body')
Hi
we upgraded our APIC from 10.0.5.2 to 10.0.5.4 and Data power 10.5.0.5R. In my openapi3 for some odd reason following code print request.body as null.
console.debug(JSON.stringify(context.get('request')))
i m posting a json body with content type application/json . same thing on v5 compatible works with
console.debug(JSON.stringify(apim.getvariable('request')))
any idea what could be going wrong ? OR am i using some deprecated code ? i did look at info center and did not find anything which would fix my issue.
Raj
------------------------------
Rajesh Solanki
------------------------------