I have a java application running in a tomcat. In one endpoint of the application I want to return a HTTP-response of type See-Other.
#GET
#Path("logout")
#Produces(MediaType.TEXT_HTML)
public Response logOut(#Context HttpServletRequest request) throws URISyntaxException {
// logout logic omitted
Response.ResponseBuilder response = Response.seeOther(new URI("../jsp/login.jsp"));
return response.build();
}
When I test this on my local machine everything works fine. On the production system however jersey seems to be unable to resolve the correct hostname from the relative path "../jsp/login.jsp". Although the host is called myhost the relative path is resolved as http://localhost:7080/myapplication/jsp/login.jsp.
new URI("../jsp/login.jsp") returns an Object where all fields are null and only path="../jsp/login.jsp". For this reason the root of the behavior must be in the Response class. I checked the documentation and figured that Response.seeOther makes a call to the Response.location method. The documentation states that
If a relative URI is supplied it will be converted into an absolute
URI by resolving it relative to the base URI of the application
Does anyone know how Jersey determines the base URI of the application? Is there some config file in the tomcat or an environment variable I set wrong?
The base URI of the application is computed using the properties of the HttpServletRequest object and is of the form:
<scheme>://<serverName>:<serverPort>/<contextPath><servletPath>/
The <serverName> and <serverPort> are usually supplied by the HTTP client, while the rest is fixed by Tomcat's or your application's configuration:
<scheme> is configured using the homonymous attribute of a <Connector> (cf. Tomcat's documentation) or can be set by the RemoteIpValve (cf. documentation),
<serverName> is supplied by the HTTP client, but can be overridden using the proxyName attribute of a connector,
<serverPort> is supplied by the HTTP client, but can be overridden using the proxyPort attribute of a connector or by the RemoteIpValve,
<contextPath> depends on how you deploy your application (e.g. it depends on the name of the WAR file in the webapps directory),
<servletPath> is configured in the web.xml descriptor or through the #ApplicationPath annotation.
What probably happens in your production environment is that Tomcat is behind a reverse proxy. To configure the base URI correctly in such a situation you have two choices:
Statically configure the correct values of scheme, secure, proxyName and proxyPort on your <Connector>,
Use the RemoteIpValve and configure the proxy server to send the original Host header and add the X-Forwarded-For and X-Forwarded-Proto headers.
If your proxy forwards different kinds of requests to Tomcat (e.g. both HTTP and HTTPS requests), the RemoteIpValve is your only choice.
Remark: The base URI can also be based on the request URI if you set the ServerProperties.LOCATION_HEADER_RELATIVE_URI_RESOLUTION_RFC7231 property to true: cf. this question.
Related
It is a web service deployed on Apache Karaf using camel-cxf. I am able to see the cxf service listing in URL localhost:8181/cxf which has some rest and soap services deployed on it.
The problem is it is returning the service listing whenever any request comes with keyword "services". For example the url http://localhost:8181/abcd/services returns cxf service listing page instead of processing the actual request.
I got to know from http://cxf.apache.org/docs/jaxrs-services-description.html that its is because of the default value of service-list-path of CXFServet is services.
Here is my Question. If I want to override this, I should set this property in etc/org.apache.cxf.osgi.cfg. This cfg file is not present under etc folder in my karaf. What are the steps to be taken if I am creating this property file manually? What features I need to install? Or creating this cfg is sufficient ?
Appreciate your help !
There should be no extra installation requirements, just create a new file etc/org.apache.cxf.osgi.cfg.
There are three settings you may be interested in:
org.apache.cxf.servlet.context = /mycxf
org.apache.cxf.servlet.service-list-path = /myservices
org.apache.cxf.servlet.hide-service-list-page = false
Where the default URL for the CXF service listing is usually like http://localhost:8181/cxf/services, with the changes above the URL would become http://localhost:8181/mycxf/myservices
If you change from false (default value) to true, then your services will be hidden and you will instead get a page stating No service was found.
Because these are initialisation settings you need to shut down Karaf for the changes to apply.
I see several points here --
The CXF framework is installed by default in karaf under the context-path /cxf.
/cxf/services can be considered as a CXF internal app that displays the list of services deployed in CXF. I don't think you can configure the name "services" here (and why would you change that?)
the "url-pattern in web.xml" you speak of (if I understand correctly) determines the context path of your servlet/application. You can specify this is camel like this:
<cxf:rsServer id="secureRsServer" address="https://0.0.0.0:8182/my/path/"
serviceClass="....">
(for the RS Server, probably same for the WS server).
I am using spring security login mechanism for my application and tested everything.Things were working fine.I have the following use case
If customer is not logged in , application will redirect customer to the login page.
On successful login, application will redirect customer back to same page from where they were redirected to the login page
this is the Java code used to redirect user to his original location
final SavedRequest savedRequest = this.requestCache.getRequest(request, response);
targetUrl = savedRequest.getRedirectUrl();
getRedirectStrategy().sendRedirect(request, response, targetUrl);
RedirectionStrategy being used here is DefaultRedirectStrategy, things were working fine. Application is now deployed on the Pre Production server and now this seems not working and I am getting 404 error.
When customer is being redirected to the home page,targetUrl is coming out as "/", I have a Spring controller named with this mapping
#RequestMapping("/")
public class HomePageController{ // home page code }
my application's current Pre-Prod urs is prepd-www.mysite.com so when sendredirect come in to action, webpage URL is getting changed to prepd-www.mysite.com/prepd-www.mysite.com
I am not sure what is causing this issue. is it because of the proxy server settings ?
Can any one suggest me about the possible root cause of this issue?
I have already tried it on all local machines and well on our QA but everything is working perfectly fine.
Current setup for the environment where this is happening is
We have 4 app server
We have one load balancer which is redirecting traffic to one of the app server.
Just a wild guess since you could not give the reverse proxy configuration, nor the exact URL used in pre prod and in developpement.
You say you are using DefaultRedirectStrategy from Spring security. This strategy has an option (contextRelative) that prepends the ServletContext path to the URL. If in your developpement system you were using the root context, that is if you were accessing home page at (for example) : http://localhost:8080/ the serlet context was empty.
But if now in preprod, the servlet context is no longer root but is say /myApp once translated by apache reverse proxy, when you redirect you get an URL of /myApp/myApp that could be translated back to what you gave.
You could try to control whether you have contextRelative as true in DefaultRedirectStrategy and if yes if you can set if to false and also control if you redirect to absolute or relative URLs.
If you are using apache in front check rewrite rule and redirect rules of apache config. Best way would be to ssh tunnel directly to application server(by skipping apache) and test. If it's working that means your application config is fine and it needs to be fixed in apache.
Are you using in preproduction tomcat or another application server?, normally if your war is calling foo and your commit to tomcat, the path for this war is
http://localhost:8080/foo/
So if you are using servlet you need specify in your web.xml that the main path is foo/*
We have an application build on Java 1.6 with Spring 3.0.3 that use Spring Security 3.0.5 and implements REST API using Spring Web with RestEasy 2.1.0.
I need to place this application (server) behind a proxy that would translate HTTPS request traffic from a REST API Client application into HTTP traffic. This change creates a “cross domain” scenario for login request : Client sends HTTPS request for login, and Server answers with redirect URL of HTTP. Currently it responses with:
”http://192.168.0.10:8090/index.html;jsessionid=64FD79...86D”,
what I need here is:
”/index.html;jsessionid=64FD79...86D”
We came with solution to make server to respond with “relative” URL instead “absolute” URL. So I tried to implement something similar with described situation here:
thread on forum.spring.io
I have set the RedirectStrategy bean with contextRelative="true" and override the redirectStrategy setter from AbstractAuthenticationTargetUrlRequestHandler within my LoginSuccessHandler extended class and I see that redirectStrategy property for HttpServletResponse object is set to true as expected. Still it not resolving the issue.
Also when changing redirectURLCC property of HttpServletResponse object using encodeRedirectURL("otherLogin") is sets something like
”http://192.168.0.10:8090/otherLogin”
and its not what I need. I need to remove whole protocol+ipaddress part of the URL. The URL property of response object is not accessible for change as it is wrapped by Filter and FilterChain interfaces implementation.
Please suggest any ideas. I suppose this kind of things should be resolved in web.xml or auth-AplicationContext.xml files not in code.
Best Regards.
Spring Security uses the following logic when sending a redirect:
public void sendRedirect(HttpServletRequest request, HttpServletResponse response, String url) throws IOException {
String redirectUrl = calculateRedirectUrl(request.getContextPath(), url);
redirectUrl = response.encodeRedirectURL(redirectUrl);
if (logger.isDebugEnabled()) {
logger.debug("Redirecting to '" + redirectUrl + "'");
}
response.sendRedirect(redirectUrl);
}
The sendRedirect method is required to behave in the following way:
This method can accept relative URLs; the servlet container must
convert the relative URL to an absolute URL before sending the
response to the client.
That means you will by deafult always get an absolute URL, no matter what's the configuration or context setting.
You have multiple options:
configure your container or application server to be aware of the public URL (for example by using AJP instead of HTTP reverse proxy, or passing HTTP headers with the public URL which is supported by some application servers), e.g. documentation for Tomcat
configure your HTTP reverse proxy to perform correct rewriting, e.g. see ProxyPassReverse in Apache mod_proxy documentation
implement a custom org.springframework.security.web.RedirectStrategy where you will manually set the Location response header and HTTP 302 status code, this should allow you to send context relative redirect as you want
Not entirely relative, but probably you might want to have a look into a 4th option using the org.springframework.web.servlet.view.UrlBasedViewResolver to rewrite the redirected URL with your external hostname as described in this answer: Override the default redirect URL in a SpringMVC application.
That should be achievable on Apache with:
ProxyPreserveHost Off
ProxyPass / http://192.168.0.10:8090
ProxyPassReverse / http://192.168.0.10:8090
and adding one more proxy reverse on the proxing host with the port.
E.g supposing your server name is proxy.example.com the fourth line would be:
ProxyPassReverse / http://proxy.exemple.com:8090
Look at this answer: Sending redirect in Tomcat web application behind a Apache 2 proxy (mod_proxy)
I work on modeshape 3.7.2 and i would like to use its REST API.
First of all i would like to know whether an API exists to Retrieve a list of available nodes in a give workspace?
Second how to interpret the syntax: http://<host>:<port>/<context>
What is <context>?
In the documentation they mention a Reponse format: Does this mean I should change the config.json file ?
Similarly to create a node: http://<host>:<port>/<context>/<repository_name>/<workspace_name>/items/<node_path>
What does the URI parameters stands for:
<context>
<workspace_name>
<node_path>
Here is the link for the URL syntax.
Is there any example for each of above cases?
First, there is no method in ModeShape's RESTful service to return all nodes from a repository. A repository can have millions of nodes with lots of content, so such a request would be make no sense and could have a monstrously-large response. Instead, there are methods to return some/all of the children (or descendants up to some depth) under a parent.
Secondly, the "context" is a term used in servlet-based applications, and typically refers to the location where the application is started within the server. By default this is "modeshape-rest", although you can change it to something else by modifying the web.xml in the WAR file.
The "response format" is typically JSON.
The RESTful service can access multiple repositories deployed in the same server, so in the URL format
http://<host>:<port>/<context>/<repository_name>/<workspace_name>/items/<node_path>
the variables in angle brackts(e.g., "<repository_name>") would be replaced with the actual value. For example, if the RESTful service is accessible on the local machine on port 8080 in the default app context "modeshape-rest" in the repository named "my-repository" with workspace "default", you can get the node at the path "/a/b/c" by making an HTTP GET request at this URL:
http://localhost:8080/modeshape-rest/my-repository/default/items/a/b/c HTTP/1.1
where the actual HTTP request might look like this:
GET /modeshape-rest/my-repository/default/items/a/b/c HTTP/1.1
Host: http://localhost:8080
Accept: application/json
and the response will be a JSON file describing the node. All of the other methods on the RESTful service use a similar pattern and are described in the service documentation.
I have the problem, that getting a ressource from my archive failed with a MalformedURLException: unknown protocol: jndi
The archive is a war file and is deployed into Websphere successfully.
When I try to access some files inside the archive via
jndi://server/context/filename
I get the MalformedURLException.
URLs with the "jndi" scheme are returned by the ServletContext#getResource method in Tomcat. However, this is non standard (i.e. the J2EE specs don't impose a URL scheme to be used in the return value of that method) and on other application servers it will be different. Always use the ServletContext#getResource method instead of trying to compose the URL directly.
Unless you registered a custom URL handler, "jndi" is not a supported protocol.
Are you trying to read the file through Java code?