How to access invoke response object variable in following steps of assembly - ibm-cloud

the assembly of my API Connect API contains two invokes. The first is calling an internal routing API to get some routing information. The response of this routing API should not be passed to the second invoke.
If I do not configure a 'response object variable' in the invoke of the routing API, the original request body is overwritten and the second API gets the result from the routing API as request body. And if I specify a 'response object variable' in the routing invoke, I can not access the content (json) of this variable in the following steps.
How can I solve this issue?
Thx 4 help.

Rather than relying on reading the request object, you can read from your configured 'response object variable' later on in the flow. For instance, if your first invoke has a response object variable set to 'resp1', you can access the JSON payload using '$(resp1.body)' later on in the flow. Using this technique will allow you to store the response of each invoke in a separate object, avoiding the overwriting issue. These response object variables can be read just like any other context variable in the flow.
For more info, check out these links in the Knowledge Center:
Invoke Policy: https://www.ibm.com/support/knowledgecenter/en/SSMNED_5.0.0/com.ibm.apic.toolkit.doc/rapim_ref_ootb_policyinvoke.html
Context Variables:
https://www.ibm.com/support/knowledgecenter/SSMNED_5.0.0/com.ibm.apic.toolkit.doc/capim_context_references.html

I don't understand this part:
[...] "And if I specify a 'response object variable' in the routing
invoke, I can not access the content (json) of this variable in the
following steps." [...]
Why can't you access the content of this variable in the following steps?
Save copy of the request...
... that you received. What I'd do is always save a copy of the data received in the invoke to a processed variable instead of the (raw) original request.
In your GatewayScript try something like this:
let objRequest = apim.getvariable("request");
let body = null;
Here I recommend you to change the body (if json) to a standard js object
if(objRequest && objRequest.hasOwnProperty("body")){
try{
body = JSON.parse(objRequest.body);
}catch(e){
body = objRequest.body;
}
}
Remember to stringify the complete object before saving it as global variable. Is the only way to store it (because you can only store a string value in this kind of variables)
apim.setvariable("objRequest", JSON.stringify(objRequest));
Retrieve copy of the request...
...that you have saved in global variables you can get it from any other GatewayScript that you want this way:
let objRequest = JSON.parse(apim.getvariable("objRequest"));
Be careful not to assign an existent name to the apim.setvariable(name, value) because if you use "request" as name instead of "objRequest" (or other), you'll be replacing the original request element, and we don't want that to happen.
If you need to set or retrieve the status.code...
...you can do it with:
let statusCode = objRequest.body.status.code;

Related

Access nested body property from HTTP resolver(AppSync)

I'm new to AWS AppSync and I am trying to access certain body property(from HTTP response) in my resolver's response mapping template.
For example: I am able to present the response as is via $util.toJson($ctx.result.body), but when I try to get some of the nested body properties it fails.
For example, imagine the body looks like this:
{
about:{
"firstName":"Chuck",
"lastName":"Norris"
}
}
and $util.toJson($ctx.result.body.about) returns null. Any thoughts?
I found a way extract the parsed body in the following way:
#set ($parsed_body = $util.parseJson($ctx.result.body))
And then I am able to access the properties via dot notation:
parsed_body.about.firstName
The part I was missing is $util.parseJson(<json-string>)
It seems that the body is a JSON string.

Extract response output from one api and needs to be passed in the 2nd

This is my response:
{"token":"eyJ0eXAiOiJKV1QiLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIiwiYWxnIjoiUlNBMV81In0.ezPR0PlML3xO08dEYnJO2QfW8wLc9Hbju1wSqBGM0MEC_YUmsOzQH9X_KvVAH0si7xUVrH74IcLcOlkqGBB5x1ZWQHzh_Zn3ej1JS_n55iXqK1bcOn2dGYjr-yTbIRzxAtUYy8FoV3aEPHwGHh6Ehc3AgOgSSq69ep4CcAUZ38Ga65cd-Aei7dfXMMqtYpHksj6K2TJ3EpFPqqZTfwmLnSomQiWNBC5u6Adkjra5zcQWNRsE2ghcaNQGtMURwjZzeNo4wMWewt1K7CobzS9JPNscK_taOIIhV3vljAf_mRkU7imujdXhchErXoTLD6-cq15txh7xJeo9o1cIm2RDLQ.UCfbgjMC5WsOf_kJsPnQOg.tfvajQljduDdtzwaWaKVxEjr4iEUeo72nS-vag6J35UIdUxdqrQYBixeKjw3vidLN7md2qNRR3fuhzejpkV05DXfyU-bDLa17wn42Ad9L5mId9mNrF9E5oVOGfnrNuoACtCgUp7ntJFBrlhzfNBXJa6AcTOrMSIX5pkXuU4ULhjFw92DqPShbUKCFQFl8UHCmU5u6263t5sSeZmwhmU65fwUeFNnbrMMePYKvRhAOEqe88djreX2j4ErAhBaDQNWVmijtqh32LFHvm_WVX8BmfY5T5-0rfMmRqZXNgesDNEdQRp1FqnSKe9rk22j4DM3y3UiXiMdS2U6eEVD_aeeQZUAqTfS7Q-cWJAxxWQLkrqeMrbLPFD6tfvac_4NQ1sgOG-CNaszkR-_0cwV1c9udQ.9FtyIM8BlR7sQXnO2ILV0CVuhiOy7oxZ8Aol2niJae9apU5T6ff5pynLqsmf6zx1fACne9vW7eNhKfup2LZWUg", "loggedInUserName": "usadm002", "loggedIndomain": "gisus"}
I need to extract token and use in 2nd API
Use JSON Extractor Postprocessor for this purpose. Add the JSON extractor element to the request which returns the above-mentioned response. Then configure it as below:
Name of the created variables: TOKEN (Any name)
JSON Path Expressions: .token
Default Values: NOT_FOUND (The Custom value you want to see by default)
Then you can use the variable in your subsequent requests as ${TOKEN}

Using OAuth2 how do I pull the access token into a variable?

I am trying to make a call to an authorization endpoint using OAuth2 with grant type Client Credentials - my call is successful - that is not an issue. However, I, now, want to take the access token that is returned and put it in a variable so I may use it in subsequent calls without having to manually cut-and-paste to my other calls.
When the call returns I see the token I desire to copy in the Access Token field at the bottom of the OAuth2 window (the one shown below that says expires in 42 minutes) AND I see it in the Authorization field on the Timeline tab of the results. I just can't figure out how to get access to it so I may dump it into variable.
The gif on the FAQ goes really fast, and does not provide step by step. Also, I didnt find any answer on YouTube or other websites, so I thought to share step by step for chaining requests on Insomnia.
Create a POST query to obtain your access token. Notice that my access token is returned in the field called "access_token", we will use this in step 3. Your return field may be different.
Create a second GET request for the API that would return the data for you. In my case, I wanted to get all users from a SCIM interface. In the Bearer tab, type in Response => Body Attribute (Insomnia will autofill).
Mouse click on the Request => Body Attribute (the one you just typed in), and select the authentication post in the dropdown "Request" (this is the one you created in step 1), and in the "Filter (JSONPath)" field, type in the $.[attribute name] - where attribute name is the response that returns from authentication call. In my case, it was access_token, see step 1 for yours.
Enjoy!!
Click No Environment > Manage Environments and you will see a base environment in JSON.
Since this is in JSON, create a { "jwt_token": "Response => Body Attribute" }" pair for your token variable. Please note that "Response => Body Attribute" needs to be configured. When you type response, hit space and this option should be available.
Once done choosing "Response => Body Attribute", it will show with some gibberish content and with red background, no worries... just click it to configure. Make sure you have the same setup.
However... you need to change your request to the route where you get the token from the server and another thing is the Filter (JSONPath or XPath) change it depending on your setup.
You should have the token, stored in jwt_token variable and can use the variable on a route that you like.
Example:
If you want to save a token that is returned in a response into an environment variable, you can use request chaining in your environment variable. Take a look at this url for more details on that https://support.insomnia.rest/article/43-chaining-requests...
Here is what you could do (what I did)
Create an environment variable
For the value of the variable, use the Response => Body Attribute and under Filter (JSONPath or XPath), choose the attribute of the token in your response body (if it is "token" then put $.token).
After that just put the token environment variable wherever you need it in the following requests.
I was not able to resolve this question but was able to get around it by defining the fields in the body of the request and bypassing the OAuth2 tab completely.
You can add it as a header, by referencing the outputs of the OAuth2 request:

Invalid_request_parameter (create and sending envelopes)

I'm trying to use a service of DocuSign API in an abap project. I want to send a document to a specific email so it can be signed. But im getting the following error:
"errorCode": "INVALID_REQUEST_PARAMETER",## "message": "The request contained at least one invalid parameter. Query parameter 'from_date' must be set to a valid DateTime, or 'envelope_ids' or 'transaction_ids' must be specified.
I tried the following:
CALL METHOD cl_http_client=>create_by_url
EXPORTING
url = l_url (https://demo.docusign.net/restapi/v2/accounts/XXXXXX')
proxy_host = co_proxy_host
proxy_service = co_proxy_service
IMPORTING
client = lo_http_client
lo_http_client->request->set_method( method = 'POST').
CALL METHOD lo_http_client->request->set_header_field
EXPORTING
name = 'Accept'
value = 'application/json'.
CALL METHOD lo_http_client->request->set_header_field
EXPORTING
name = 'X-DocuSign-Authentication'
value = get_auth_header( ). (json auth header)
CALL METHOD lo_http_client->request->set_cdata
EXPORTING
data = create_body( ).
This is my body:
CONCATENATE
`{`
`"emailSubject": "DocuSign REST API Quickstart Sample",`
`"emailBlurb": "Shows how to create and send an envelope from a document.",`
`"recipients": {`
`"signers": [{`
`"email": "test#email",`
`"name": "test",`
`"recipientId": "1",`
`"routingOrder": "1"`
`}]`
`},`
`"documents": [{`
`"documentId": "1",`
`"name": "test.pdf",`
`"documentBase64":` `"` l_encoded_doc `"`
`}],`
`"status": "sent"`
`}` INTO re_data.
The api request to get the Baseurl is working fine. (I know the error is quite specific what the problem is, but i cant find any sources on the docusign api documentation that one of the mentioned parameters should be added to the request)
Thank you in regards
The error message seems to indicate that you're Posting to an endpoint that requires certain query string parameters -- but you're not specifying them as expected in the query string. I'd suggest you check the DocuSign API documentation for the operation you are using, to determine what query string parameters it requires, and then ensure that you're including those parameters in your request URL.
If you can't figure this out using the documentation, then I'd suggest that you update your post to clarify exactly what URL (endpoint) you are using for the request, including any querystring parameters you're specifying in the URL. You can put fake values for things like Account ID, of course -- we just need to see the endpoint you are calling, and what qs params you're sending.
To create an envelope, use
https://demo.docusign.net/restapi/v2/accounts/XXXXXX/envelopes
instead of
https://demo.docusign.net/restapi/v2/accounts/XXXXXX
Thank you for all the answers, i found the mistake. Creating the request wasn´t the problem. I was using the wrong "sending"-method -_-.
now its working :)
lo_rest_client->post( EXPORTING io_entity = lo_request_entity ).

Using save or put with Restangular results in "undefined" being included in URL

I am using Restangular to download an object, update it and then attempt to save back to the server using the save method. Here is the code that retrieves the object:
Restangular.one("survey", surveyID).getList().then (
function (response) {
$scope.survey = response[0];
}
);
This sets $scope.survey to a properly "restangularized" object, with the fields that come back from the GET request, along with the methods like save, put, etc.
If I then invoke the following function after making some edits to the $scope.survey object:
$scope.saveChanges = function () {
$scope.survey.save();
};
restangular tries to use the URL /survey/1/undefined for the PUT request (1 is the correct ID for the object).
My survey object doesn't have an id field (it's surveyID instead), and so I suspected this might be the problem. However, replacing the surveyID field with an id field changed the URL to be /survey/1/undefined/1
I have stripped down the object returned by the GET request to be just primitives, and this does not change the situation.
Why is the incorrect route being generated?
II discovered the problem was actually with the REST service; when called with GET /surveys/1, it was returning an array with a single object in it, rather than returning the object itself.
I think this caused restangular to think that a collection was being accessed (note that I was having to call getList rather than get in order to get a properly restangularized object).