Issue with Forwarded Header and Multiple Values in Spring - java

According to the RFC7239 specification, syntax for Forwarded Header is as follows:
Forwarded: by=<identifier>;for=<identifier>;host=<host>;proto=<http|https>
These values are used by Spring (all recent versions), if present, in order to reflect the client-originated protocol and address (when allowed through a configuration). There is a problem when using multiple values in this header:
# Multiple values can be appended using a comma
Forwarded: for=192.0.2.43,for=198.51.100.17;proto=https;host=xxx.yyy.com;by=10.97.9.10
The code in UriComponentsBuilder#adaptFromForwardedHeaders:798-800 gets the first Forwarded Header, if multiple are found, splits it by comma and uses only the first part:
UriComponentsBuilder adaptFromForwardedHeaders(HttpHeaders headers) {
try {
String forwardedHeader = headers.getFirst("Forwarded");
if (StringUtils.hasText(forwardedHeader)) {
String forwardedToUse = StringUtils.tokenizeToStringArray(forwardedHeader, ",")[0];
....
}
Using the example above, the forwardedToUse variable becomes Forwarded: for=192.0.2.43 where all useful information is trimmed.
Is this really an issue or there is something that I am missing? And if this is really a problem, how can I deal with it.
Thanks a lot in advance!

It seems that there is an issue in Spring with Forwarded header in case of multiple values. It is fixed with the commit below and will be available in next release:
GitHub Issue: Issue with Forwarded Header and Multiple Values
Spring Framework Commit: Do not tokenize Forward header value
Release: Spring 5.2.9.RELEASE

Related

how to accept fixed length message by spring rest api

I need to expose one rest API with spring boot that has to accept message content in fixed-length format and, as is(i.e without disturbing fixed-length message content ), need to put into IBM MQ to pass received fixed-length message to the back end system (IBM mainframe system)via IBM MQ
I would be requesting you to help me with the sample code for this requirement
Fixed-length format messages, for example:
20011228YF2001122814313425 Forest St Marlborough MA017525083828200600
Fixed-length format messages use ordinal positions, which are offsets to identify where fields are within the record. There are no field delimiters. An end-of-record delimiter is required, even for the last record.
Welcome stackoverflow asking question area. As I see this is more into javax.validation.constraints package. In your entity, you do something like
public class Market {
#NotNull
#Size(max=4)
private String marketCode;
// getters/setters
}
So when you try to bind values from #RequestBody Market market, it will throw error regarding the length

Fetching string value from JMS header

I'm trying to figure out how to pull a value out of a JMS header so I can route it to a specific queue dynamically. I have spent hours trying various methods to extract the value but I haven't been successful. See the below snippet which explains what I'm after. Any help or even pointing me in the right direction would be much appreciated.
// fetch the queue name from the JMS header
String queue = "jms:queue:" + header("__DestinationQueue").toString();
choice = choice
.when(header("Match").isEqualTo("true"))
.id("JMSDaemonOutboundRouteBuilder")
.to(queue);
choice = choice
.otherwise().bean(UnroutableMessageLogAction.class)
.bean(EndConversationAction.class, "process")
.bean(ESBMessageCompleteAction.class, "process")
.to("jms:queue:UNROUTED").endChoice();
The data is definitely contained in the header (I've run .isEqualTo comparisons on the header value to confirm this) I am just having issues extracting the actual value into the string.
The solution was to use toD instead of to which natively allows routing to JMS header values. Link below:
http://camel.apache.org/message-endpoint.html

How to verify optional parameters using Wiremock Request Matching Stubs(JAVA Usage)?

How to match a wiremock POST request with some optional JSON parameters & any values?
Being new to Stack community, I have raised the below query(afraid that it would be marked as duplicate) in the post (link mentioned above) but it has been deleted stating its the different question and need to raise new question.
Below is my query on top of it:
If the optional parameter is not present in the request than the solution provided in the above post suffice the purpose.
But If the optional parameter is present and we need to check that it contains specific values only (say not null) then how to do that using request matching in wiremock.
Kindly provide your inputs as I am new to wiremock
For instance:
{
"optional1"="ValueAlwaysYESIfPresent",
"optional2"="ValueAlwaysNOIfPresent"
}
Thanks in advance.
Have a look at http://wiremock.org/docs/request-matching/
instead of going to other places
basically you can do matching like
withQueryParam("optional2", equalTo("ValueAlwaysNOIfPresent"))
Or
withQueryParam("optional2", matching(".*12345.*"))
and many other things.

Adding custom step definitions to Karate framework

I have a need to extract a field parsed from a "complex" response header and use that value later in the test.
It seems that the "header" keyword in Karate is set up for setting request headers, not parsing response headers.
Is there a way to add a custom step definition maintaining access to the scenario variable stores? It appears the variable stores are private in the StepDefs class, and there doesn't seem to be a way to extend it easily.
You can get access to the response headers. Please look at the documentation for responseHeaders.
That said, the match header short-cut is most likely what you are looking for.
Karate's philosophy is that you never need to write custom step-definitions.
edit: some examples, sounds like you just need to do some string manipulation of the Location header ? You can freely mix JS code into Karate expressions.
* def location = responseHeaders['Location'][0]
# assume location = 'foo?bar=baz'
* def bar = location.substring(location.indexOf('bar=') + 4)

Handling multiple parameters in a URI (RESTfully) in Java

I've been working on a small scale web service in Java/Jersey which reads lists of user information from clients contained in XML files. I currently have this functioning in all but one aspect: using multiple parameters in the URI to denote pulling multiple sets of user information or multiple sets of client information. I have a version which currently works, but is not the best way nor what the project description calls for.
Currently, my code looks like this:
#Path("Client/{client}/users")
public class UserPage
{
#GET
#Produces(MediaType.TEXT_HTML)
public String userChoice(#PathParam(value = "client") final String client)
{****Method here which handles a list of 'users'****}
#GET
#Path("{name}")
#Produces(MediaType.TEXT_HTML)
public String userPage(#PathParam(value = "client") final String client, #PathParam(value = "name") final String name)
{****Method here which handles 'user' information****}
The first method handles a list of users from a 'client' denoted by "{client}" in the URI. The second method delivers 'user' information denoted by "{name}" in the URI. Both will function with a single argument. Currently, in order to handle multiple 'users' I have "{name}" comma separated like "Client/Chick-Fil-A/users/Phil,Bradley". I can parse this after using #PathParam and create an array of these 'users', but again, I feel this is not the best way to handle this, and the project description calls for something different.
Is there a way to accomplish this same task with a URI formatted as "Client/Chick-Fil-A;cd=Phil,Bradley"? (The ;cd= is what's giving me the most trouble.)
I also need to be able to use this format for multiple clients, i.e. "Client;cd=Chick-Fil-A,Subway/users;cd=Phil,Bradley".
Edit: To clarify the project:
The client information is contained in 6 separate files. Each of these files has the same 3 users (this is a proof of concept, effectively). I need to be able to pull different subsets of information, for instance, user Phil from McDonalds and Chick-Fil-A, or users Phil and Peter from McDonalds, or users named Peter from all clients, etc.
You cannot use '=' in the URL path since it's a reserved character. However there are many other character you can use as delimiters such as '-' and ','. So instead of '=' you can use '-'. If you really really want to use '=' then you will have to URL-encode it; however, I would strongly recommend against this because it may make things more complicated then it should be.
You can see the grammar of the URL string here:
http://www.w3.org/Addressing/URL/url-spec.txt
Copy and search the following string to skip to the path grammar:
path void | segment [ / path ]
segment xpalphas
That said, I believe HTTP request is usually used for request single resource only. So my personal opinion is to not implement the service the way you implemented. For getting multiple clients I would use query parameters as filters like this:
Client/{cName}/users?filters=<value1>,<value2> ...
Edit: From the business case you got there, it seems like you probably need service like
/users?<filters>
/clients?<filters>
So say you want to get Peter from all clients then can have a request of this form:
/users?name=Peter
Similarly, if you want to get Jack and Peter from Starbucks then you can do:
/users?name=Peter,Jack&client=Starbucks
Hopefully this helps.
Query strings have the following syntax and you can have multiple parameters with the same name:
http://server/path/program?<query_string>
where query_string has the following syntax:
field1=value1&field1=value2&field1=value3…
For more details check out this entry in Wikipedia: http://en.wikipedia.org/wiki/Query_string

Categories

Resources