Camel Rest-DSL required param ignored - java

I have a Rest API, created with Camel Rest-DSL. There is a rest, that consumes GET with a list of params, some of which are mandatory.
Route config:
rest().get("/{{camel.rest.version}}/myget")
.param()
.name("accountNumber")
.dataType("string")
.type(RestParamType.query)
.required(true)
.endParam()
.param()
.name("someId")
.dataType("string")
.type(RestParamType.query)
.required(false)
.endParam()
.produces(REST_PR_CN_TYPE)
.responseMessage().code("200").message("OK").endResponseMessage()
.responseMessage().code("500").endResponseMessage()
.route().routeId("rst_cardsInfo")
.log(LoggingLevel.INFO, "ApiRq Recieved http request")
.log(LoggingLevel.DEBUG, "AccountNumber: ${header.accountNumber}, SomeId: ${header.someId}")
.id("rst_rst_info_recieved")
.to("direct:drt_rst_info")
.endRest();
When I open swagger-ui generated page, my API is looks fine. Param accountNumber is marked as required, someId - as not required.
Using any other tool I can send a request without any params and receive HTTP.200 as a response. I expected, that if a param is required, but not present in request, the request would fail. Spring Rest for example makes sure that all mandatory params are present.
Is there any mandatory params presence validation in Camel? May be I misconfigured something?

Ah okay. There is no / only a little bit of validation today in the rest-dsl. It relies on the chosen HTTP component (servlet, restlet, undertow etc.) to do that.
But frankly we can improve thise and let camel-core do some pre-validation if the options has been specified as in your example.
I have logged a ticket: https://issues.apache.org/jira/browse/CAMEL-12533

Thank you, #Claus Ibsen.
From Camel 2.22 version onwards, now we can validate incoming client request.
The validation is turned off by default. In order to configure it, we need to use clientRequestValidation as follow :
restConfiguration()
.component("restlet").host("localhost").port("port")
.clientRequestValidation(true);
For more details visit : Client Request Validation - Apache Camel Manual

Related

Provide the actual HTTP GET request within the response

I would like to provide the actual get request in a response. I am free to choose between placing that information into the header or the body of the response.
The current project setup includes:
Nginx as reverse proxy
Spring boot application
which are potential candidates to put in that logic.
Request:
GET http://localhost/api/users/2/photos/2
Response:
BODY {"some": "values",
"_request": "GET http://localhost/api/users/2/photos/2"}
or
HEADERS "custom-header-get-request": "GET http://localhost/api/users/2/photos/2"
BODY {"some": "values"}
I can easily add the information to the response of each Responseobject within the Controllers of the spring boot application. This approach is quite cumbersome, as it leads to a lot of codechanges and allways needs to be in mind that each Controller should take care of providing the requestinformation to the response, achieving the first solution.
Which other options do i have?

Is it possible to return a application/json from a Spring Integration http inbound-channel-adapter?

I have an inbound-channel-adapter that forwards message to router and router has one mapping property which calls service activator where I am trying to trigger one REST POST service which accepts input JSON and produce output JSON.
In this case, service activator reutrns null but since http has to return a response.(In inbound-channel-adapter, I am using status-code-expression="T(org.springframework.http.HttpStatus).NO_CONTENT"
I'm using spring-integration v4.3.6
No, it’s possible. Since this component is one-way, there is nothing to return - just only status code header. By default it is 200 OK.
If you would like to return something, you should consider to use HTTP Inbound Gateway instead.
Otherwise your question isn’t clear

Spring Integration: How to filter specific headers - only possible with header mapper?

In spring integration you can set the properties mapped-request-headers, mapped-response-headers and header-mapper in an outbound-gateway.
My target is to filter out specific headers, so I need some kind of blacklist. But the first two attributes are whitelists. I can either say mapped-request-headers="*", then every header will be passed, or I can put some specific headers, but then only these headers will be passed. But that's not what I want.
I could somehow overwrite the header mapper and add this bean to the header-mapper attribute, but is this the way of doing this? (I wonder why headers can be whitelisted but not blacklisted). Isn't there some functionality to set "filter spring added headers" and "pass manually added headers" or something?
You don't say what Spring Integration version you are using, or the type of endpoint you are using.
Since version 4.3, mappers that extend from AbstractHeaderMapper (AMQP, SOAP, XMPP) now support negated headers "!foo,!bar,baz*".
If you are not using one of these protocols, you can use a header filter upstream of the endpoint (for outbound) or right after the endpoint (inbound).
For the HTTP header mapper (DefaultHttpHeaderMapper) you can wire in a custom bean of that type where you add any standard headers you wish to exclude via the excludedOutboundStandardRequestHeaderNames and excludedInboundStandardResponseHeaderNames properties.

Handle JSON request with Apache Camel

I want to handle an HTTPs request that a 3rd party is doing towards my system. The requests contains a JSON object
I have tried using the Jetty component of Camel but when the 3rd party performs the requests Camel throws the following exception:
org.apache.camel.RuntimeCamelException: Cannot read request parameters due Invalid parameter, expected to be a pair but was {"id":"321","rec":"533","status":"ok"}
The Jetty endpoint is defined in blueprint as:
<camel:endpoint id="getRequestEndpoint" uri="jetty:{{webServiceProtocol}}://{{jettyIp}}:{{jettyPort}}/getRequest?sslContextParametersRef=sslContextParameters"/>
Am I missing something or are in a totally wrong path?
Make sure that your client is sending the appropriate Content-Type HTTP request header for JSON, which is:
Content-Type: application/json
It looks like it wasn't sent and the Jetty component falls back to form data interpretation.
Make sure you also add expected bean type to your endpoint definition, like this:
.post()
.type(User.class)
.to("direct:your-queue")
This is strictly speaking not an answer, because in this case you get a different exception shown below. But I hope it helps someone.
org.apache.camel.InvalidPayloadException: No body available of type:
com.example.User but has value: {id=69, name=Hello world} of type:
java.util.LinkedHashMap

JAX-RS (jersey) -> Angular.js via REST

I have a jersey server up and running. When running from browser directly I get the correct response. However when I try to access the rest service from angular.js's $resource I get the following error in the console when trying to access to the correct url. I've tried to read all materials online, like http://simplapi.wordpress.com/2013/04/10/jersey-jax-rs-implements-a-cross-domain-filter/ to setup a CORS filter, but the guide seems to be dated and cryptic. (im using the newest implementation of jersey).
Failed to load resource: Origin localhost:63342 is not allowed
by Access-Control-Allow-Origin.
method that makes the data I need available in jersey.
#Path("/id/{id}")
#GET
#Produces(MediaType.APPLICATION_JSON)
public boolean validateSSN(#PathParam("id") String id) {
IdValidator idv = new IdValidator(id);
return idv.Validate();
}
accessor method in angular.js:
services.factory('ReplyFactory', function ($resource) {
console.log("test");
return $resource(baseUrl + '/myproject/api/validate/id/:id', {id: '#id'},
{'get': { method: 'GET' }});
});
Well what you need to do is to ensure that all responses from your resources have following http headers:
Access-Control-Allow-Origin - specifies from which origins requests should be accepted (localhost:63342 in your case)
Access-Control-Allow-Headers - specifies which headers are allowed to be used via CORS
Access-Control-Allow-Methods - specifies which methods are allowed to be used via CORS
And there are other headers like Access-Control-Allow-Credentials and etc.
So you just need to add at least Access-Control-Allow-Origin header to your responses. How you can do it depends on your environment.
You can manually define those headers on each resource .
You can define Jersey filter to add CORS headers to all responses
You can use servlet filter to add CORS headers to all responses
There are also specific solutions for Tomcat and Jetty
There many ways how to do it but all of it is about the same thing - you just add an extra header to your server responses.

Categories