I am using WSO2 Integrator 6.6.0 to make a blocking HTTP GET to a REST API that returns a JSON response (HTTP 200 OK).
But I never see the response body inside my sequences. I am not sure what I am doing wrong, having exhausted all available documentation and other threads.
Sequence doing the call (simplified to anonymize), which logs the response afterwards:
<!-- Remove XML body as not needed for GET request -->
<payloadFactory media-type="json">
<format></format>
<args></args>
</payloadFactory>
<header name="Accept" value="application/json" scope="transport"/>
<property name="NO_ENTITY_BODY" value="true" scope="axis2" type="BOOLEAN" />
<call blocking="true">
<endpoint>
<http method="GET" uri-template="http://my-api/order-status">
</endpoint>
</call>
<property name="RESPONSE" scope="default" type="STRING" value="true"/>
<log level="full">
<property name="response-log" value="Received response"/>
<property expression="$body" name="response-body"/>
<property expression="json-eval($)" name="json-eval-body"/>
</log>
This results simply into a log line - with no response body at all!
INFO {org.apache.synapse.mediators.builtin.LogMediator} - To:
http://my-api/order-status, WSAction: urn:mediate, SOAPAction:
urn:mediate, MessageID:
ID:414d51204343494153303131202020209ca4175f28ac422e, Direction:
response, response-log = Received response, response-body =
<soapenv:Body
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"></soapenv:Body>,
json-eval-body = {}, Payload: {}
I can see the request in my API application and I can also see what it correctly returns a response body in its logs. Also, using Postman to do the same request I receive the following JSON response with 200 OK and Content-Type appication/json:
{
"order_status": "NOT_FOUND"
}
Inside WSO2 I do not see anything! I want to be able to convert the response into XML format.
What could be wrong?
Before making a REST call, it is necessary to remove the headers from the main call.
Put this snippet before the call mediator:
<property name = "FORCE_HTTP_CONTENT_LENGTH" scope = "axis2" type = "STRING" value = "true" />
<property action = "remove" name = "REST_URL_POSTFIX" scope = "axis2" />
<property action = "remove" name = "TRANSPORT_HEADERS" scope = "axis2" />
As I understand it should solve.
Can you modify the NO_ENTITY_BODY property as follows and try this mediation again.
<property name="NO_ENTITY_BODY" action="remove" scope="axis2"/>
Having simplified this configuration for this question, I had missed that having the following property set in my proxy service:
<property name="OUT_ONLY" scope="default" type="STRING" value="true"/>
Means that WSO2 is ignoring the response from the API. Removing this property resolved the issue for the following config:
<header name="Accept" value="application/json" scope="transport" />
<property action="remove" name="NO_ENTITY_BODY" scope="axis2"/>
<property name="messageType" scope="axis2" type="STRING" value="application/json"/>
<call blocking="true">
<endpoint key="conf:/endpoints/FX_TRADING_API_ORDERSTATUS.xml"/>
</call>
Related
Scenario:
The API basically calls an endpoint to get the token and then sets the token in the header and calls another endpoint along with other query parameters.
Problem:
I'm getting the null resolving to address issue.
[2022-11-09 18:08:19,327] INFO {LogMediator} - {api:MsaasproEsb} To: http://www.w3.org/2005/08/addressing/anonymous, WSAction: , SOAPAction: , MessageID: urn:uuid:e763462f-c7dc-4f3d-a8ba-b23c5f66a241, correlation_id: 7dba4bab-4218-48ca-9871-e4c2d249a91b, Direction: request, Payload: {"Data": {"status": 200, "id": 190, "user_id": "secpapi", "email": "Faisal.furqan#secp.gov.pk", "token": "9704e4de2acde3af0686c22d409f831db3d1fd76"}}
[2022-11-09 18:08:19,328] INFO {TRACE_LOGGER} - Sending message through endpoint : null resolving to address = https://msaaspro.com/api/v1/scan/pep-scan/?fullname={uri.var.name}&searchtype=fuzzy&fathername={uri.var.fatherName}&dobyear={uri.var.dobYear}&cnic={uri.var.cnic}&mobile={uri.var.mobile}&country={uri.var.country}&name_similarity=90
[2022-11-09 18:08:19,328] INFO {TRACE_LOGGER} - SOAPAction:
[2022-11-09 18:08:19,328] INFO {TRACE_LOGGER} - WSA-Action:
[2022-11-09 18:09:17,775] INFO {SourceHandler} - Writer null when calling informWriterError
[2022-11-09 18:09:17,775] WARN {SourceHandler} - STATE_DESCRIPTION = Socket Timeout occurred after accepting the request headers and the request body, INTERNAL_STATE = REQUEST_DONE, DIRECTION = REQUEST, CAUSE_OF_ERROR = Connection between the client and the EI timeouts, HTTP_URL = /msaaspro/send, HTTP_METHOD = POST, SOCKET_TIMEOUT = 180000, CLIENT_ADDRESS = /127.0.0.1:55470, CONNECTION http-incoming-4 Correlation ID : 965986e6-2d6b-4108-aefe-3a7a648eb61a
[2022-11-09 18:10:44,079] INFO {SourceHandler} - Writer null when calling informWriterError
[2022-11-09 18:10:44,079] WARN {SourceHandler} - STATE_DESCRIPTION = Socket Timeout occurred after accepting the request headers and the request body, INTERNAL_STATE = REQUEST_DONE, DIRECTION = REQUEST, CAUSE_OF_ERROR = Connection between the client and the EI timeouts, HTTP_URL = /msaaspro/send, HTTP_METHOD = POST, SOCKET_TIMEOUT = 180000, CLIENT_ADDRESS = /127.0.0.1:58755, CONNECTION http-incoming-5 Correlation ID : 1fc72034-a9d1-46ad-9198-d18810065c10
[2022-11-09 18:11:19,011] INFO {SourceHandler} - Writer null when calling informWriterError
[2022-11-09 18:11:19,011] WARN {SourceHandler} - STATE_DESCRIPTION = Socket Timeout occurred after accepting the request headers and the request body, INTERNAL_STATE = REQUEST_DONE, DIRECTION = REQUEST, CAUSE_OF_ERROR = Connection between the client and the EI timeouts, HTTP_URL = /msaaspro/send, HTTP_METHOD = POST, SOCKET_TIMEOUT = 180000, CLIENT_ADDRESS = /127.0.0.1:58781, CONNECTION http-incoming-6 Correlation ID : 7dba4bab-4218-48ca-9871-e4c2d249a91b
Source code:
<?xml version="1.0" encoding="UTF-8"?>
<api context="/msaaspro" name="MsaasproEsb" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="POST" uri-template="/send">
<inSequence>
<property description="username" name="username" scope="default" type="STRING" value="json-eval($.username)"/>
<property description="password" name="password" scope="default" type="STRING" value="json-eval($.password)"/>
<call>
<endpoint>
<http method="post" statistics="enable" uri-template="https://msaaspro.com/api/v1/auth/auth-token/">
<suspendOnFailure>
<initialDuration>-1</initialDuration>
<progressionFactor>-1</progressionFactor>
<maximumDuration>0</maximumDuration>
</suspendOnFailure>
<markForSuspension>
<retriesBeforeSuspension>0</retriesBeforeSuspension>
</markForSuspension>
</http>
</endpoint>
</call>
<property description="token" name="token" scope="default" type="STRING" value="json-eval($.Data.token)"/>
<property description="Authorization" name="Authorization" scope="transport" type="STRING" value="fn:concat('Token ', get-property('token'))"/>
<property description="name" name="uri.var.name" scope="default" type="STRING" value="json-eval($.name)"/>
<property description="fatherName" name="uri.var.fatherName" scope="default" type="STRING" value="json-eval($.fatherName)"/>
<property description="dobYear" name="uri.var.dobYear" scope="default" type="STRING" value="json-eval($.dobYear)"/>
<property description="uniqueKey" name="uri.var.cnic" scope="default" type="STRING" value="json-eval($.cnic)"/>
<property description="country" name="uri.var.country" scope="default" type="STRING" value="json-eval($.country)"/>
<property description="mobile" name="uri.var.mobile" scope="default" type="STRING" value="json-eval($.mobile)"/>
<log level="full"/>
<call>
<endpoint>
<http method="get" statistics="enable" trace="enable" uri-template="https://msaaspro.com/api/v1/scan/pep-scan/?fullname={uri.var.name}&searchtype=fuzzy&fathername={uri.var.fatherName}&dobyear={uri.var.dobYear}&cnic={uri.var.cnic}&mobile={uri.var.mobile}&country={uri.var.country}&name_similarity=90">
<suspendOnFailure>
<initialDuration>-1</initialDuration>
<progressionFactor>-1</progressionFactor>
<maximumDuration>0</maximumDuration>
</suspendOnFailure>
<markForSuspension>
<retriesBeforeSuspension>0</retriesBeforeSuspension>
</markForSuspension>
</http>
</endpoint>
</call>
</inSequence>
<outSequence>
<respond/>
</outSequence>
<faultSequence/>
</resource>
</api>
Question:
My exact question is why I'm getting null resolving issue while I've set properties for all the parameters that I've passed to the endpoint. I'm able to call the first endpoint and I successfully get the token but somehow I'm unable to call the second endpoint.
In the property mediators, when you use XPath or JSONPath expressions, you need to use the expression parameter instead of value. For example,
<property description="token" name="token" scope="default" type="STRING" value="json-eval($.Data.token)"/>
should be updated as follows,
<property description="token" name="token" scope="default" type="STRING" expression="json-eval($.Data.token)"/>
Can you update all the property mediators as above and try them out?
I couldn't find a <respond/> mediator after the call mediator in your insequence. To send the response back to the client you need to have Respond Mediator.
Regarding the log message Sending message through endpoint : null resolving to address, since we have used an anonymous endpoint, the trace logger couldn't resolve a name for the endpoint. That's why it's printing a null in the trace log.
I'm not sure why you are seeing null in the Trace logs. But I assume that's the expected behavior with an HTTP Endpoint. I see a typo in your second URL. Check the following. After pep-scan you shouldn't have a / before the query params.
uri-template="https://msaaspro.com/api/v1/scan/pep-scan?fullname={uri.var.name}&searchtype=fuzzy&fathername={uri.var.fatherName}&dobyear={uri.var.dobYear}&cnic={uri.var.cnic}&mobile={uri.var.mobile}&country={uri.var.country}&name_similarity=90"
If that doesn't resolve the issue, try adding the following property before the second HTTP call.
<property action="remove" name="TRANSPORT_HEADERS" scope="axis2"/>
Add the above in the following order.
<property action="remove" name="TRANSPORT_HEADERS" scope="axis2"/>
<property description="token" name="token" scope="default" type="STRING" value="json-eval($.Data.token)"/>
<property description="Authorization" name="Authorization" scope="transport" type="STRING" value="fn:concat('Token ', get-property('token'))"/>
<property description="name" name="uri.var.name" scope="default" type="STRING" value="json-eval($.name)"/>
<property description="fatherName" name="uri.var.fatherName" scope="default" type="STRING" value="json-eval($.fatherName)"/>
<property description="dobYear" name="uri.var.dobYear" scope="default" type="STRING" value="json-eval($.dobYear)"/>
<property description="uniqueKey" name="uri.var.cnic" scope="default" type="STRING" value="json-eval($.cnic)"/>
<property description="country" name="uri.var.country" scope="default" type="STRING" value="json-eval($.country)"/>
<property description="mobile" name="uri.var.mobile" scope="default" type="STRING" value="json-eval($.mobile)"/>
<log level="full"/>
<call>
<endpoint>
<http method="get" statistics="enable" trace="enable" uri-template="https://msaaspro.com/api/v1/scan/pep-scan/?fullname={uri.var.name}&searchtype=fuzzy&fathername={uri.var.fatherName}&dobyear={uri.var.dobYear}&cnic={uri.var.cnic}&mobile={uri.var.mobile}&country={uri.var.country}&name_similarity=90">
<suspendOnFailure>
<initialDuration>-1</initialDuration>
<progressionFactor>-1</progressionFactor>
<maximumDuration>0</maximumDuration>
</suspendOnFailure>
<markForSuspension>
<retriesBeforeSuspension>0</retriesBeforeSuspension>
</markForSuspension>
</http>
</endpoint>
</call>
If you still see the issue, enable wire logs and compare the outgoing message with a direct request and try to find what's different.
We have two ways to send requests in wso2 APIM:
1- send mediator
2- call mediator
Unfortunately, I cannot use any of these mediators!
for example this request: http://jsonplaceholder.typicode.com/posts/
I need this approach for get token from a server and then use it in payload of main request for authentication.
could anyone help me please?! :)
I didn't get any error or special log!
<log level="custom">
<property name="text" value="###############################33"/>
</log>
<call blocking="false">
<endpoint>
<http method="GET" uri-template="http://jsonplaceholder.typicode.com/posts/"/>
</endpoint>
</call>
<log level="custom">
<property name="text" value="###############################"/>
</log>
You could find related blogs "WSO2 API Manager & OAuth2 Protected Endpoint" and answer to this question
The idea is to
call the token endpoint with the appropriate grant type(usually client secret grant is used for system to system calls).
Then extract the token using the script mediator
Then use the that token to call the API attaching the token to "Authorisation Bearer:" header.
Please give this a try.
Let's use the below properties before the call mediator. If your response is not a json payload, you need to set the expected payload content type to the ContentType and messageType properties.
<property action="remove" name="NO_ENTITY_BODY" scope="axis2"/>
<property name="ContentType" scope="axis2" value="application/json"/>
<property name="messageType" scope="axis2" value="application/json"/>
After adding the above properties into the sequence, it should look like the below.
<sequence>
<property action="remove" name="NO_ENTITY_BODY" scope="axis2"/>
<property name="ContentType" scope="axis2" value="application/json"/>
<property name="messageType" scope="axis2" value="application/json"/>
<call blocking="true">
<endpoint>
<http method="GET"
uri-template="http://www.mocky.io/v2/5c9ddf51330000b12c3f253a"/>
</endpoint>
</call>
</sequence>
I'm creating a POST API service to upload files in WSO2EI. Request using multipart/form-data.
I got error
Access to XMLHttpRequest at 'x' from origin y has been blocked by CORS policy: Request header field x-requested-with is not allowed by Access-Controll-Allow-Headers in preflight response
I only got the error when hit the service from frontend using vue js.
I already added option method
<resource methods="OPTIONS" uri-template="/*">
<inSequence>
<property name="Access-Control-Request-Headers" scope="transport" type="STRING" value="authorization,content-type"/>
<sequence key="gov:commons/AccessControlAllow.xml"/>
<property name="RESPONSE" scope="default" type="STRING" value="true"/>
<respond/>
</inSequence>
<outSequence/>
<faultSequence/>
</resource>
sequence AccessControlAllow.xml
<?xml version="1.0" encoding="UTF-8"?>
<sequence name="AccessControlAllow" trace="disable" xmlns="http://ws.apache.org/ns/synapse">
<property name="Access-Control-Request-Headers" value="Authorization,Content-Type, Access-Control-Allow-Origin" scope="transport" type="STRING"/>
<property name="Access-Control-Allow-Methods" scope="transport" type="STRING" value="GET,POST,PUT,DELETE,OPTIONS"/>
<property name="Access-Control-Allow-Headers" scope="transport" type="STRING" value="Origin, X-Requested-With, Content-Type, Accept"/>
<property name="Access-Control-Allow-Origin" scope="transport" type="STRING" value="*"/>
</sequence>
I also added this sequence (AccessControlAllow.xml) before sending response. I got the error only when the request using mulltipart/form-data and hit from vue.js. Anyone can help me to solve this problem?
This might be because, You have defined a OPTION resource in your API. If you have defined OPTIONS as a resource method, then EI sends the request to the backend service to collect the information.
Therefore, Check the API definition and remove OPTION call if exist.
Setup
Client -> WSO2EI -> Backend Server
The backend Server forces my WSO2EI to be of some specific User-Agent (Say 'I_M_ABC').
Issue
The solution is to set the user agent before using the call mediator to call the back end server. However, the WSO2EI forces the User-Agent always to be "Axis2".
Code Snippets
<property name="HTTP_METHOD" scope="axis2" value="POST"/>
<header name="Action" value="''"/>
<header name="To" expression="fn:concat($ctx:uri.var.server.url, $ctx:uri.var.server.path)"/>
<property action="remove" name="REST_URL_POSTFIX" scope="axis2"/>
<property name="PRESERVE_WS_ADDRESSING" value="true"/>
<property name="preserveProcessedHeaders" value="true" scope="default"/>
<property name="messageType" scope="axis2" type="STRING" value="text/xml"/> -
<property name="UsesAgent" scope="default" type="STRING" value="I_AM_ABC"/>
<header expression="get-property('UsesAgent')" name="User-Agent" scope="transport"/>
<header expression="get-property('messageType')" name="Content-Type" scope="transport"/>
LOG MESSAGE
Relevant log entries
POST /path_to_resource HTTP/1.1[\r][\n]
Content-Type: text/xml; charset=UTF-8[\r][\n]
cache-control: no-cache[\r][\n]
User-Agent: Axis2[\r][\n]
Host: www.myhostcom[\r][\n]
What have I done
changed passthru-http.properties for user-agent [did not work]
changed axis.xml commented out userAgent [did not work]
I also tried to preserve the user agent and from the client call, passed user agent. However, that also changed to Axis2.
changed nhttp.properties file (http.user.agent.preserve=true) - Did not work.
changed passthru-http.properties file (http.user.agent.preserve=true) - Did not work.
Thoughts?
Thanks in advance.
I am working on the WSO2 ESB Proxy service, which involves exposing the internal RESTful service via SOAP endpoint on the ESB.
My RESTful service requires Content-type = "application/rdf+xml". I tried setting it using all 3 properties mentioned in the documentation: messageType, ContentType and CONTENT_TYPE. However, the request Content-type still remains "application/xml".
Here is an excerpt from my sequence that calls REST service:
<property xmlns:ns="http://org.apache.synapse/xsd" name="REST_URL_POSTFIX" value="/record/12345" scope="axis2" type="STRING"/>
<property name="HTTP_METHOD" value="PUT" scope="axis2" type="STRING"/>
<property name="messageType" value="application/rdf+xml" scope="axis2" type="STRING"/>
<property name="ContentType" value="application/rdf+xml" scope="axis2" type="STRING"/>
<property name="CONTENT_TYPE" value="application/rdf+xml" scope="axis2" type="STRING"/>
<send>
<endpoint name="CQ">
<address uri="http://my_url" format="pox">
</address>
<property xmlns:ns="http://org.apache.synapse/xsd" name="Authorization" expression="fn:concat('Basic ', base64Encode('username:password'))" scope="transport"/>
<property name="OSLC-Core-Version" value="2.0" scope="transport"/>
<property name="Accept" value="application/rdf+xml" scope="transport"/>
</endpoint>
</send>
I tested it with TCPMon and no matter what Content-type property I use, request still contains "application/xml".
Please advice.
Can you try WSO2 ESB 4.7.0 with following configuration? Note that, I have changed the address format from "pox" to "rest"
<property xmlns:ns="http://org.apache.synapse/xsd" name="REST_URL_POSTFIX" value="/record/12345" scope="axis2" type="STRING"/>
<property name="HTTP_METHOD" value="PUT" scope="axis2" type="STRING"/>
<property name="messageType" value="application/rdf+xml" scope="axis2" type="STRING"/>
<property name="ContentType" value="application/rdf+xml" scope="axis2" type="STRING"/>
<property name="CONTENT_TYPE" value="application/rdf+xml" scope="axis2" type="STRING"/>
<send>
<endpoint name="CQ">
<address uri="http://my_url" format="rest">
</address>
<property xmlns:ns="http://org.apache.synapse/xsd" name="Authorization" expression="fn:concat('Basic ', base64Encode('username:password'))" scope="transport"/>
<property name="OSLC-Core-Version" value="2.0" scope="transport"/>
<property name="Accept" value="application/rdf+xml" scope="transport"/>
</endpoint>
</send>
These are the http headers sent now (captured from tcpmon)
PUT /record/12345 HTTP/1.1
Cookie: region1_configure_menu=none; region3_registry_menu=none; region4_monitor_menu=none; region5_tools_menu=none; JSESSIONID=54D2911FCD5559C6B2F723E7C6FA9B44; requestedURI="../../carbon/service-mgt/index.jsp?region=region1&item=services_list_menu"; current-breadcrumb=manage_menu%2Cservices_menu%2Cservices_list_menu%23
Authorization: null
OSLC-Core-Version: 2.0
Content-Type: application/rdf+xml
Accept: application/rdf+xml
Transfer-Encoding: chunked
Host: www.foo.com:8080
Connection: Keep-Alive
User-Agent: Synapse-PT-HttpComponents-NIO
In the configuration you have attached, you have specified the format of the address uri as "pox" .
<address uri="http://my_url" format="pox">
This will be the reason that you are getting content-type as application/xml always. Please remove this attribute and try. It should be
<address uri="http://my_url">
If you still see the issue, then try to switch to the NHTTP transport as suggested by RaviU. For that, you can first backup the axis2.xml (ESB_HOME/repository/conf/axis2/axis2.xml) as axis2_back.xml and then rename the axis2_nhttp.xml file (same location) as axis2.xml.
Can you set the content type property like this;
<property name="Content-Type” value="application/rdf+xml" scope="transport"/>
Please remove other content-type properties..
If you define like this;
[1]<property name="messageType" value="application/rdf+xml" scope="axis2" type="STRING"/>
[2]<property name="ContentType" value="application/rdf+xml" scope="axis2" type="STRING"/>
[1] for, to select messageformatter
[2]for, to select message builders
Edit;
try like this
<inSequence>
<log level="custom">
<property name="in seq --------------of proxy" expression="$trp:Content-Type"/>
</log>
<property name="messageType"
value="application/json"
scope="axis2"
type="STRING"/>
<property name="Content-Type"
value="application/json"
scope="transport"
type="STRING"/>
<log level="custom">
<property name="in seq --------------of proxy" expression="$trp:Content-Type"/>
</log>
<send>
<endpoint>
<address uri="http://localhost:5555/com"/>
</endpoint>
</send>
Sometimes, you have to enable those message formatters in axis2.xml before using them.
Check this article out. It may help if you haven't done so yet.
http://wso2.com/library/articles/axis2-configuration-part2-learning-axis2-xml#mf