I'm trying to add some additional static data to an inbound http message (received as URL parameters) payload before submitting it to an outbound http form based endpoint. My mule config is as follows :
<flow name="login" doc:name="login">
<http:inbound-endpoint exchange-pattern="request-response" address="http://localhost:8081/login" doc:name="Login"/>
<http:body-to-parameter-map-transformer doc:name="Body to Parameter Map"/>
<http:outbound-endpoint address="http://localhost:8090/mayapp/Main/login.do"
method="POST" contentType="application/x-www-form-urlencoded" exchange-pattern="request-response">
</http:outbound-endpoint>
</flow>
The above transforms the URL parameters to a http form POST (name/values pairs) very nicely. What I need now is the ability to add new name-value pairs to the POST(ed) data ? The form I'm posting to expects some static data (posted as hidden HTML fields) that I would like to handle as part of the transformation process.
I've managed to accomplish this using a custom component. I'm wondering if there's an easier way to handle this using Mule's native transformers / message processors !
First I would use a transformer and not a component for this, as it is really a transformation you're doing on the payload data.
Second I can't think of another transformer than the Groovy one to modify the Map payload created by the body-to-parameter-map-transformer. Something like:
<script:transformer>
<script:script engine="groovy">
<script:text>
payload['newKey'] = 'newValue'
</script:text>
</script:script>
</script:transformer>
You can use an expression-component as well:
<expression-component doc:name="change_payload">
<![CDATA[#[ message.payload = 'foo';]]]>
</expression-component>
Related
Following are the steps that I need to peform
Make http request call to a sevice which returns a json that has many urls.
Extract all the urls using regular expression extractor
Make http request call to all the exctracted urls asynchronously.
Is there a way we can achieve this? I tried parallel controller but, if I am not wrong, it requires all the request to be mentioned as its child sampler. I don't want to write each and every request manually. Is there a way we can change urls dynamically after running the test plan?
It's better to use JSON Extractor if the server returns URLs in JSON format
Once you have the URLs in form of JMeter Variables like:
url_1=http://example.com
url_2=http://example.org
........
........
url_matchNr=X
add Parallel Sampler to your Test Plan
add JSR223 PreProcessor as a child of the Parallel Sampler
Put the following code into "Script" area:
1.upto(vars.get('url_matchNr') as int, { index ->
sampler.addURL(vars.get('url_' + index))
})
I am using golang´s fasthttprouter and have followed the examples and defined a router like this:
router.GET("/customer/account/detail/:accountId", myHandler.customerAccountDetailHandler)
Then I call to my service as http://locahost:9296/customer/account/detail/2
But I realised that I do not want to have the parameters as part of the endpoint , I rather prefer to use normal parameters by calling my service like this:
http://locahost:9296/customer/account/detail?accountId=2&sort=1
Is it possible to be done with fasthttprouter? How?
Thanks in advance
J
The query parameter should be accessible from the request context.
You should have a handler that takes a *fasthttp.RequestCtx argument. This RequestCtx can access the URI and the query params on that URI. That should look something like this:
ctx.URI().QueryArgs().Peek("accountId")
You'll have to update your handler to use this query parameter instead of the route param you were previously using. The same would also apply for the sort param.
Also, your router would have to be updated to route /customer/account/detail to your updated handler (i.e. you'll want to remove /:accountId from your route).
Your questions is similar to this one:
Get a request parameter key-value in fasthttp
You can retrieve the parameters of the request in this way:
token = string(ctx.FormValue("token"))
Have a look at my complete response here
https://stackoverflow.com/a/57740178/9361998
Documentation: https://godoc.org/github.com/valyala/fasthttp#RequestCtx.FormValue
Hi I want to add a query parameter Age = 23
I tried adding
message.inboundProperties.'http.query.params'.Age = '23'
In a expression
<expression-component doc:name="Expression"><![CDATA[message.inboundProperties.'http.query.params'.Age= '23';]]></expression-component>
It won't work.
Inbound properties are Immutable hence you must add it in outbound property to add a query param in your outbound http connector you can use the below
<http:request config-ref="HTTP_Request_Configuration" path="outway" method="POST" doc:name="HTTP">
<http:request-builder>
<http:query-param paramName="Age" value="23"/>
</http:request-builder>
</http:request>
To add properties to an outgoing message they need to be in the outbound scope:
message.outboundProperties.'http.query.params'.Age= '23'
You are trying to modify inbound properties but you can´t, they are inmutable
Properties have two main scopes: inbound and outbound.
Inbound properties are immutable, are automatically generated by the message source and cannot be set or manipulated by the user. They contain metadata specific to the message source that prevents scrambling of data formats or other processing mishaps later in the message’s lifecycle. A message retains its inbound properties only for the duration of the flow; when a message passes out of a flow, its inbound properties do not follow it (see image below).
https://docs.mulesoft.com/mule-fundamentals/v/3.7/mule-message-structure
You must add it to outbound as Ryan said.
I am trying to achieve the functionality where i have to call two different backends / target endpoints that have completely different interface in a sequence. Output of one call becomes input to the second one upon an error condition from the first call.
I would like to know how to implement this. I am new to Apigee so details will help me.
It sounds like you need to do a ServiceCallout in the request flow.
Set up your Target as whatever the second server is that you need to talk to in the normal flow. Then create a policy to callout to your first target:
<ServiceCallout name="myPolicy">
<Request clearPayload="false" variable="myRequest"/>
<Response>myResponse</Response>
<HTTPTargetConnection>
<Properties/>
<URL>http://example.com</URL>
</HTTPTargetConnection>
</ServiceCallout>
Note the Response block puts the headers and payload from the response into an object that you can then extract variables from using "myResponse" as the <Source> in the ExtractVariables policy.
Then you can build a new request for your target with the variables you set in the ExtractVariables by using an AssignMessage policy
Service Callout
http://apigee.com/docs/api-services/content/call-services-or-apis-using-servicecallout
ExtractVariables
http://apigee.com/docs/api-services/content/extract-message-content-using-extractvariables
AssignMessage
http://apigee.com/docs/api-services/content/generate-or-modify-messages-using-assignmessage
I have java object that I would like to pass as a custom header to my request on the http outbound gateway. Below is a snippet
<int:gateway id="service" service-interface="MyService" default-request-channel="requestChannel" default-reply-channel="replyChannel">
<int:method name="doSomething" payload-expression="#args[0] + ',' + #args[1]">
<int:header name="method_name" value="login"/>
<int:header name="service_identifier" value="myService"/>
</int:method>
</int:gateway>
<int:header-enricher input-channel="requestChannel" output-channel="gatewayChannel">
<int:header name="user_context" expression="T(UserContextHolder).getContext()"/>
</int:header-enricher>
<int-http:outbound-gateway request-channel="gatewayChannel" url="myURL" mapped-request-headers="user_context, service_identifier, method_name, HTTP_REQUEST_HEADERS"
http-method="POST" reply-channel="replyChannel"/>
Where UserContext could be a java object
UserContext implements Serializable {
String userId;
RequestParameters params;
ScopeEnum scope;
....
}
The problem I have is header user_context is not mapped in the header. From the logs, I can see that the DefaultHttpHeaderMapper is requesting for a Converter or ConversionService. See below -
09:54:59,488 - WARN main org.springframework.integration.http.support.DefaultHttpHeaderMapper - Header 'X- user_context' with value 'UserContextImpl#5e3ca754' will not be set since it is not a String and no Converter is available. Consider registering a Converter with ConversionService (e.g., <int:converter>)
How do I do this please ?
Thanks!
Standard HTTP headers are in key:value format and both key and value are strings.
You try to send object as a HTTP header value which is not very wise (and almost impossible because there may be some limits on the size of headers - for example 8KB Apache default limit).
You have three options:
Consider not using HTTP outbound gateway and use JMS instead (the best one in my opinion)
Add transformer which will serialize UserContext to String (if it was relatively short string it would be ok, in the other case I'd not recommend it)
Implement custom converter UserContext->String as described in section Datatype Channel Configuration of the spring reference documentation:
http://static.springsource.org/spring-integration/reference/htmlsingle/#channel-configuration