Setting Uri dynamically in HTTP Location Header - spring-integration

I implemented a Rest service that creates an Employee. In the response message I want to dynamically set the HTTP Location header with the newly created Employee resource Uri.
The below code is working fine and I am able to see the value in Location header as expected. However I have the Uri hardcoded in the EmpService and I want it to be dynamic. How do I extract/pass Uri information to the EmpService bean?
Config.xml
<int-http:inbound-gateway
request-channel="httpPostChannel"
reply-channel="responseChannel"
path="/emp"
supported-methods="POST"
message-converters="converters"
request-payload-type="com.samples.jaxb.Employee"/>
<int:service-activator ref="empService" method="post"
input-channel="httpPostChannel" output-channel="responseChannel"/>
EmpService.java
public Message<Employee> post (Message<Employee> msg) {
Employee emp = empDao.createEmployee(msg.getPayload());
return MessageBuilder.withPayload(emp)
.setHeader(org.springframework.http.HttpHeaders.LOCATION, "http://localhost:8080/RestSample/emp/" + emp.getEmpId())
.build();
}

Actually even right now your URI is dynamic:
"http://localhost:8080/RestSample/emp/" + emp.getEmpId()
OTOH you always can inject it via setter or #Value property during application start from some external property.
Or you even can do that extracting some property/header from the incoming Message.
However I guess you would like to know the host and port you are ran on.
The host you can know via InetAddress.getLocalHost().
The port you can extract via an appropriate ServletContainer vendor API, e.g. for Tomcat: Get the server port number from tomcat with out a request.
With Spring Boot you can just use #LocalServerPort:
* Annotation at the field or method/constructor parameter level that injects the HTTP
* port that got allocated at runtime. Provides a convenient alternative for
* <code>#Value("${local.server.port}")</code>.
Although... I guess this one should be enough for:
.setHeader(org.springframework.integration.http.HttpHeaders.REQUEST_URL,
request.getURI().toString())
I mean that your incoming Message after <int-http:inbound-gateway> has header set. In my test case with Spring Boot and random Tomcat port it looks like:
"http_requestUrl" -> "http://localhost:64476/service/?name=foo"

Related

Spring Integration: pass-through custom http header converted to lowercase

My application is supposed to pass through a custom http header, hence I tell the inbound http gateway to map that header as request and response header:
#Bean
public IntegrationFlow myFlow() {
return IntegrationFlows
.from(Http.inboundGateway("/myresource/{transactionId}")
.mappedRequestHeaders("X-My-Header",
HTTP_REQUEST_HEADER_NAME_PATTERN)
.mappedResponseHeaders("X-My-Header",
HTTP_RESPONSE_HEADER_NAME_PATTERN)
...
The header gets passed through alright, but it is converted to lowercase, i.e. I find x-my-header in the response. I know that http headers are case-insensitive, still I would prefer to keep the header in its original form. Is that possible?
According HTTP RFC headers are case-insensitive, therefore the logic in your app has to be changed to ignore case for those names.
Tomcat team suggests to implement a custom Filter to override response headers: https://bz.apache.org/bugzilla/show_bug.cgi?id=58464.
Anyway I would reconsider a client app logic do not deal with case. Nothing to do with Spring Integration though.

what is x-Application-Context header?

What is this response header (x-Application-Context) stands for? is it specific to Spring framework?
what does the below header means?
X-Application-Context airtel-project-service:aws:27094
does it reveals any senstive information like hostname or port number?
Spring Boot ApplicationContextHeaderFilter does add this header.
Class description:
OncePerRequestFilter to add a X-Application-Context header that contains the ApplicationContext ID.
AppliationContext ID is a name for the deployed application that this context belongs to.
You can change the default behavior by setting management.add-application-context-header property to false.
management.add-application-context-header=true # Add the "X-Application-Context" HTTP header in each response.
Spring Boot resolved issue 1308.

Katana+OWIN Context Get HTTP Referrer?

IOwinContext does not appear to have the HTTP Referrer in it, and I need to grab it. What is the right way to get that particular variable? IOwinContext has several Typed PEMs but I don't see referer in particular.
The system I am working is self-hosted.
Thanks.
The OwinContext doesn't have 'HTTP Referer' as item in Request header. This has been renamed in Owin self host context. It's now known as 'Referer'. So once you have object of owin context you can get the information by using:
context.Request.Headers["Referer"]

HTTP POST request from Android App denied on Domain but works using IP address‏

I'm trying to send a HTTP POST request to a PHP file on my web hosting server from my Android app.
That request contains the data from the app and is validated or saved on the server and then the PHP file sends a JSON response which is received by the Android device and the actions are taken accordingly like logging in or registering etc.
Now the problem that has arisen is that till now I didn't have a paid DOMAIN instead only a HOSTING service. That Hosting Service gave me a Server IP address to access the Index.php file I had uploaded.
So in my Android code I had written the url to be connected as http://10x.xxx.xx.xx/index.php/
and the request and response were working totally fine.
Now I have purchased a Domain name from Godaddy.com and I'm forwarding that domain name to the Server IP I had and when I open it in browser it's working perfectly fine. And so I changed the ip on which the request should be sent in my Android code to http://www.sampleurl.com/index.php/
This is my index.php file
if (isset($_POST['tag']) && $_POST['tag'] != '') {
// get tag
$tag = $_POST['tag'];
//do other authorization stuff
}
else
echo "Access Denied";
Now the problem is when I'm using the Server Ip address to connect it goes into the if block and functions correctly. But when I use the Domain name it always returns Access Denied.
The Logcat shows:
03-18 02:59:08.780: E/JSON(30892): Access Deniedn
03-18 02:59:08.780: E/JSON Parser(30892): Error parsing data org.json.JSONException: Value Access of type java.lang.String cannot be converted to JSONObject
03-18 02:59:08.780: W/System.err(30892): java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String org.json.JSONObject.getString(java.lang.String)' on a null object reference
Now I don't know how a letter 'n' is appended after 'Access denied' neither why the request is not being served correctly.
P.S. I have used forwarding instead of updating the NS at the domain. Can that possibly be causing the issue?
With the DNS being configured to forward, your post-request got lost. Check your server logs. You need to set it to be a type A record.

ASP.NET MVC5 OWIN rejects long URLs

I am creating an ASP.NET MVC5 action method that implements a password reset endpoint and accepts a click-through from an email message containing a token. My implementation uses OWIN middleware and closely resembles the ASP.NET Identity 2.1 samples application.
As per the samples application, the token is generated by UserManager and embedded into a URL that is sent to the user by email:
var token = await UserManager.GeneratePasswordResetTokenAsync(user.Id);
var encoded = HttpServerUtility.UrlTokenEncode(Encoding.UTF8.GetBytes(token));
var uri = new Uri(Url.Link("ResetPasswordRoute", new { id = user.Id, token = encoded }));
The link in the email message targets an MVC endpoint that accepts the token parameter as one of its route segments:
[Route("reset-password/{id}/{token}"]
public async Task<ActionResult> PasswordResetAsync(int id, string token)
{
token = Encoding.UTF8.GetString(HttpServerUtility.UrlTokenDecode(token));
// Implementation here
}
However, requests to this endpoint (using a URL generated in the above manner) fail with Bad Request - Invalid URL.
It appears that this failure occurs because the URL is too long. Specifically, if I truncate the token segment, it connects correctly to the MVC endpoint (although, of course, the token parameter is no longer valid). Specifically, the following truncated URL works ...
http://localhost:53717/account/reset-password/5/QVFBQUFOQ01uZDhCRmRFUmpIb0F3RS9DbCtzQkFBQUFzcko5MEJnYWlrR1RydnVoY2ZwNEpnQUFBQUFDQUFBQUFBQVFaZ0FBQUFFQUFDQUFBQUNVeGZZMzd4OTQ3cE03WWxCakIwRTl4NkVSem1Za2ZUc1JxR2pwYnJSbmJ3QUFBQUFPZ0FBQUFBSUFBQ0FBQUFEcEpnVXFXS0dyM2ZPL2dQcWR1K2x6SkgxN25UVjdMYlE2UCtVRG4rcXBjU0FBQUFE
... but it will fail if one additional character is added ...
http://localhost:53717/account/reset-password/5/QVFBQUFOQ01uZDhCRmRFUmpIb0F3RS9DbCtzQkFBQUFzcko5MEJnYWlrR1RydnVoY2ZwNEpnQUFBQUFDQUFBQUFBQVFaZ0FBQUFFQUFDQUFBQUNVeGZZMzd4OTQ3cE03WWxCakIwRTl4NkVSem1Za2ZUc1JxR2pwYnJSbmJ3QUFBQUFPZ0FBQUFBSUFBQ0FBQUFEcEpnVXFXS0dyM2ZPL2dQcWR1K2x6SkgxN25UVjdMYlE2UCtVRG4rcXBjU0FBQUFEf
I believe that the default IIS configuration setting for maxUrlLength should be compatible with what I am trying to do, but I have also tried explicitly setting it to a larger value, which did not solve the problem.
However, using Fiddler to examine the server response, I can see that the working URL generates a server response with the following header ...
Server: Microsoft-IIS/8.0
... whereas the longer URL is rejected with a response containing the following header ...
Server: Microsoft-HTTPAPI/2.0
This seems to imply that the URL is not being being rejected by IIS, but by a middleware component.
So, I am wondering what that component might be and how I might work around its effect.
Any suggestions please?
Many thanks,
Tim
Note: Although my implementation above Base64 encodes the token before using it in the URL, I have also experimented with the simpler approach used in the sample code, which relies on the URL encoding provided by UrlHelper.RouteUrl. Both techniques suffer from the same issue.
You should not be passing such long values in the application path of the URL as they are limited in length to something like 255 characters.
A slightly better alternative is to use a query string parameter instead:
http://localhost:53717/account/reset-password/5?token=QVFBQUFOQ01uZDhCRmRFUmpIb0F3RS9DbCtzQkFBQUFzcko5MEJnYWlrR1RydnVoY2ZwNEpnQUFBQUFDQUFBQUFBQVFaZ0FBQUFFQUFDQUFBQUNVeGZZMzd4OTQ3cE03WWxCakIwRTl4NkVSem1Za2ZUc1JxR2pwYnJSbmJ3QUFBQUFPZ0FBQUFBSUFBQ0FBQUFEcEpnVXFXS0dyM2ZPL2dQcWR1K2x6SkgxN25UVjdMYlE2UCtVRG4rcXBjU0FBQUFEf
That should be safe for at least 2000 characters (full URL) depending on the browser and IIS settings.
A more secure and scalable approach is to pass a token inside an HTTP header.

Resources