I want to enrich a Camel exchange with content fetched from some external web service. However, when calling that service, I do not want all the headers on my incoming exchange to be mapped onto HTTP headers, just some selected ones should be mapped. Hence, I try to use a HeaderFilteringStrategy as follows:
override fun configure() {
from(direct("webservice-query"))
.setHeader("Accept").constant("application/json")
.setHeader(Exchange.HTTP_PATH)
.simple("/partner:\${header.$PARTNER_ID_HEADER}")
.setHeader(Exchange.HTTP_QUERY).constant("attachments=true")
.enrich(http(partnerDbUrl)
.headerFilterStrategy(myHeaderFilterStrategy)
.httpMethod(HttpMethods.GET), PartnerAggregationStrategy
)
}
where myHeaderFilterStrategy is an instance of a custom HeaderFilteringStrategy. However, the HTTP component does not use this strategy. Instead, a default HttpHeaderFilteringStrategy is used. Why? What is wrong with the above route configuration? How can I set a custom header filtering strategy, or otherwise prevent unwanted headers polluting the HTTP request?
Related
I know ResponseCache attribute can caching page in client side by http headers attribute cache-control.
And ResponseCache middleware, it caching page on server (same http headers as ResponseCache attribute).
I compare these, it seems no different, same features, same condition.
Server side caching is no different from ResponseCache attribute, they both don't let the request into controller action, or these have different request pipeline ?
So, What kind of scenarios would choose ResponseCache middleware/ ResponseCache attribute?
From documentations and source code, we can find:
Response Caching Middleware
determines when responses are cacheable, stores responses, and serves responses from cache.
ResponseCache Attribute
specifies the parameters necessary for setting appropriate headers in response caching.
It is used to configure and create (via IFilterFactory) a ResponseCacheFilter. The ResponseCacheFilter performs the work of updating the appropriate HTTP headers and features of the response. The filter:
Removes any existing headers for Vary, Cache-Control, and Pragma.
Writes out the appropriate headers based on the properties set in the ResponseCacheAttribute.
Updates the response caching HTTP feature if VaryByQueryKeys is set.
For more information, please check:
ResponseCachingMiddleware source
code
ResponseCacheAttribute source code
I am trying to customize the response of a bayeux server response so that i can add some header parameters before sending it back to UI. I am able to add header values in the request using customize method in a LongPollingTransport. Much help needed.
CometD tries to abstract away from the underlying protocol.
When you use WebSocket, for example, the concepts of request headers and response headers simply do not exist anymore.
As such, it is way better that if you have additional information to send to the client, well that additional information should go in the CometD messages rather than in HTTP headers.
Furthermore, when using HTTP as a transport, a single HTTP response may carry multiple messages, so it is not clear to what CometD message the additional information would refer to.
Your question is too generic (does not say why you want to add headers, does not say what specific header, etc.) to get a precise answer, but bottom line is that you typically don't want to use HTTP headers with CometD.
I am calling a HTTP endpoint before my message reaches the apikit:router.
By the time the message reaches the apikit:router, it has lost all the original HTTP headers. Because of that the router is not able to figure out the intended method.
Actually I am able to copy the inbound properties in a session variable, after the HTTP call I am able to revert them as outbound property. Then I have my api router in another flow, so the outbound property gets coverted to inbound property again. This solution works fine, but the flow looks pretty ugly. (as I had to do this copy for about 10 headers)
Is there any better workaround ? Also I am trying to avoid manually dealing with these headers.
Wrap the HTTP call within the enricher, it will preserve the http inbound properties and the payload of the original call. Like this,
<enricher target="#[flowVars.resultOfInnerHTTP] source="#[payload]">
<http:request...../>
</enricher>
<apikit:router.../>
I'm storing some data as session variables in a mule flow that involves a mid-flow http call to an external service. I need this data for a subsequent branch of the flow logic, hence the session variable. However, I do not want this data to go out with the http call as http headers. Is there a way to limit which session variables mule includes as http headers in a given call?
If you want to decide what session property to propagate you can write a custom session handler and inject it into your http connector something like this:
<http:connector name="httpConnector">
<service-overrides sessionHandler="your_session_handler" />
</http:connector>
An example of a custom session handler can be found here
That said I'd like to echo David Dossot's answer: session variables should seldom be used, especially knowing how Mule leaks them by default. If you want to propagate something, you should set it explicitly as an outbound property and mule will propagate it.
Use flow variables: session variables should seldom be used, especially knowing how Mule leaks them by default.
Flow variables (aka invocation properties) should be unaffected by endpoint interactions, this by design. Any other behaviour would be a bug. If your variables do not need to extend further than a flow, use flow variables, not session variables.
session variables are not sent across http calls, only session ID is sent via cookie (usually)
if you need to pass some data via http call to external domain - include them in GET, for example, as cookie are not shared
Just getting my head around message queues and Redis MQ, excellent framework.
I understand that you have to use .RegisterHandler(...) to determine which handler will process the type of message/event that is in the message queue.
So if I have EventA, EventB etc should I have one Service which handles each of those Events, like :
public class DomainService : Service {
public object Any(EventA eventA) {...}
public object Any(EventB eventA) {...}
}
So these should be only queue/redis list created?
Also, what If I want a chain of events to happen, so for example a message of type EventA also has a handler that sends an Email providing handlers earlier on the chain are successful?
ServiceStack has no distinction between services created for MQ's, REST, HTML or SOAP services, they're the same thing. i.e. they each accept a Request DTO and optionally return a Response DTO and the same service can handle calls from any endpoint or format, e.g HTML, REST, SOAP or MQ.
Refer to ServiceStack's Architecture diagram to see how MQ fits in.
Limitations
The only things you need to keep in mind are:
Like SOAP, MQ's only support 1 Verb so your methods need to be named Post or Any
Only Action Filters are executed (i.e. not Global or Attribute filters)
You get MqRequest and MqResponse stubs in place of IHttpRequest, IHttpResponse. You can still use .Items to pass data through the request pipeline but any HTTP actions like setting cookies or HTTP Headers are benign
Configuring a Redis MQ Host
The MQ Host itself is completely decoupled from the rest of the ServiceStack framework, who doesn't know the MQ exists until you pass the message into ServiceStack yourself, which is commonly done inside your registered handler, e.g:
var redisFactory = new PooledRedisClientManager("localhost:6379");
var mqHost = new RedisMqServer(redisFactory, retryCount:2);
mqHost.RegisterHandler<Hello>(m => {
return this.ServiceController.ExecuteMessage(m);
});
//shorter version:
//mqHost.RegisterHandler<Hello>(ServiceController.ExecuteMessage);
mqHost.Start(); //Starts listening for messages
In your RegisterHandler<T> you specify the type of Request you want it to listen for.
By default you can only Register a single handler for each message and in ServiceStack a Request is tied to a known Service implementation, in the case of MQ's it's looking for a method signature first matching: Post(Hello) and if that doesn't exist it looks for the fallback Any(Hello).
Can add multiple handlers per message yourself
If you want to invoke multiple handlers then you would just maintain your own List<Handler> and just go through and execute them all when a request comes in.
Calling different services
If you want to call a different service, just translate it to a different Request DTO and pass that to the ServiceController instead.
When a MQ Request is sent by anyone, e.g:
mqClient.Publish(new Hello { Name = "Client" });
Your handler is invoked with an instance of type IMessage where the Request DTO is contained in the Body property. At that point you can choose to discard the message, validate it or alter it.
MQ Requests are the same as any other Service requests
In most cases you would typically just forward the message on to the ServiceController to process, the implementation of which is:
public object ExecuteMessage<T>(IMessage<T> mqMsg)
{
return Execute(mqMsg.Body, new MqRequestContext(this.Resolver, mqMsg));
}
The implementation just extracts the Request DTO from the mqMsg.Body and processes that message as a normal service being passed a C# Request DTO from that point on, with a MqRequestContext that contains the MQ IHttpRequest, IHttpResponse stubs.