I have a Tomcat 6 webserver running my application and I am seeing some very strange redirect behaviour.
I expect to access my application at the internal URL http://appteam.testdomain.co.uk/test and that this will return a 302 redirect to http://appteam.testdomain.co.uk/test/ which then serves up index.html, the front page of the application.
However, a GET for http://appteam.testdomain.co.uk/test currently returns a 302 to http://appteam.testdomain.co.ukteam.testdomain.co.uk/test/
How would I debug this weird redirect and what Tomcat config could possibly be causing this behaviour?
EDIT
For clarity the strangeness here is that a request for
http://appteam.testdomain.co.uk/test
is being redirected to
http://appteam.testdomain.co.ukteam.testdomain.co.uk/test/
Note the mangled domain.
EDIT2
#Sean - I am not doing the redirect myself. Something deep within Tomcat seems to be handling this for me. Let me know which parts of the various Tomcat XML files would help to diagnose this and I will post them.
I have worked out the answer and it is very specific to the way my app is deployed. Tomcat sits behind an NGINX proxy which forwards almost all traffic to Tomcat. The Proxy is used to handle some URLs differently. It turns out that Tomcat is returning a correct 302 to
http://appteam.testdomain.co.uk/test/
but the NGINX proxy is mangling this into
http://appteam.testdomain.co.ukteam.testdomain.co.uk/test/
This behaviour seems not to be an error. Jetty also sends a 302 redirect if the request points to a directory without the trailing slash.
The Apache URL Rewriting Guide contains a section about the Trailing Slash Problem.
Related
I have a Java Web application deployed in tomcat.
I receive 400 Bad request from Tomcat 8 if my URL is like this
https://<serverurl>?cmisSelector=object&objectId=TyNGT0wjJSMwMDAjMDAjIyMj&filter=cmis:createdBy,a:b:ab,a:b:abc&renditionFilter=cmis:thumbnail,application/pdf,image/bmp,image/gif,image/jpeg,image/png
Which is encoded as
https%3A%2F%2F%3Cserverurl%3E%3FcmisSelector%3Dobject%26objectId%3DTyNGT0wjJSMwMDAjMDAjIyMj%26filter%3Dcmis%3AcreatedBy%2Ca%3Ab%3Aab%2Ca%3Ab%3Aabc%26renditionFilter%3Dcmis%3Athumbnail%2Capplication%2Fpdf%2Cimage%2Fbmp%2Cimage%2Fgif%2Cimage%2Fjpeg%2Cimage%2Fpng
But if i remove the a:b:ab,a:b:abc and renditionFilter=cmis:thumbnail,application/pdf,image/bmp,image/gif,image/jpeg,image/png from the URL then the it works, this URL is formed like below
https://<serverurl>?cmisSelector=object&objectId=TyNGT0wjJSMwMDAjMDAjIyMj&filter=cmis:createdBy
Seems to be some URL encoding issue but not able to find out the exact issue.
By default Tomcat returns a HTTP Bad Request (400) if the URL contains a forward or backward slash / (%2F) and \ (%5C) respectively. This is done as a security measure.
You can disable that feature and allow those characters by setting the following system properties (for instance in catalina.properties or in CATALINA_OPTS):
-Dorg.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true
### You may not need this one, as you only have forward slashes
-Dorg.apache.catalina.connector.CoyoteAdapter.ALLOW_BACKSLASH=true
I have a website (Liferay portal 6.1 and Tomcat 7.0) which is having HTTP and HTTPS URL like below.
https://stackoverflow.com/questions/ask
https://stackoverflow.com/profile
I follow below steps and I am getting Forbidden error:
I fill some form details in 2nd URL.
Before submitting that form I open 1st URL in a new tab.
Then if I come back to 1st URL and do a submit then I found a forbidden error.
I checked JSESSIONID at both tabs, Ids are same. What may be the issue? Any idea guys?
It's not worth investing time in making http/https mixed mode work (in my opinion). Bite the bullet and just go https always. Even if you'd fix this issue now, chances are that you'll run into more issues later, eating up more of your time. And when you run into other issues, they're highly likely security sensitive.
Do yourself a favor - unconditionally redirect ALL http traffic to https. It's 2016, there's nothing unusual with this any more.
Edit after your comment: Do this especially if it's an old system (by the way, this was obvious when you mentioned Liferay 6.1. Assuming you're using CE, it's long out of updates): Configure the use of https anywhere you can easily get your hands on. Unconditionally add the HSTS header to take care of the rest. No need to touch any ancient logic. E.g. set
web.server.protocol=https
in your portal-ext.properties. Add the HSTS header to your Apache httpd unconditionally (assuming you have Apache httpd, otherwise use this Liferay App from yours truly).
I have a Grails application that is running in Tomcat 7 under IIS 7, using the Jakarta Isapi Tomcat connector version 1.2.30 and I'm having trouble getting the error handling to behave how I'd like. The Tomcat connector is configured in uriworkermap.properties to forward all requests below the application's URL to Tomcat:
/OrderSubmission/* = worker1
The Grails application has its own custom error pages which work fine when the application is running on a development machine without IIS / the Tomcat connector, but when on the server, if custom error pages are switched on in IIS, these always override the ones in the Grails application. This means that where I have a specific page to handle a certain exception type, e.g. in UrlMappings.groovy:
"500"(controller: 'error', action: 'itemNotFound', exception: ItemNotFoundException)
...I'm instead seeing the static 500 error page that I've pointed IIS at.
If I instead turn on detailed errors in IIS I get the correct error pages through from my Grails application - however, if a request is made for a URL outside of the application's context, I then see the detailed IIS 404 page, which is unacceptable. If I change the Tomcat connector's uriworkermap.properties to include everything from the root downwards then I instead see a default Tomcat 404 error page. I've tried getting the Tomcat connector to default to custom pages by setting the error_page option in isapi_redirect.properties to point to my IIS static custom pages like so:
error_page=/%d.htm
...but this doesn't work, and I can't find any example of using this setting anywhere.
What I need to happen is for the custom Grails error pages to be shown - unless the URL being requested is outside the application or the application is down, at which point I need custom static error pages to be shown.
Has anyone managed to achieve this?
TIA
I ended up making my error page controller methods return a status of 200 (OK), unless dealing with an AJAX request:
class ErrorController {
def pageNotFound() {
if (!request.xhr){
response.status = 200
}
}
}
IIS is set to 'Custom error pages'.
This prevents IIS stepping in and providing the custom static pages that I provide, unless the requested URL is outside the scope of the Grails application.
The error status is retained for AJAX requests in order to allow the caller to properly deal with the result.
I'm unsure whether it's satisfactory practice to return 200 from the application on error, particularly with regard to search engines - however it seems that even without this change, when an error occurs and the response is ultimately returned to the browser from IIS it has a status of 200, according to Fiddler.
While deploying my app to mochahost, I met the problem between servlet and GWT-RPC communicate. The error shows:
HTTP Status 404 - /403.shtml
type Status report
message /403.shtml
description The requested resource (/403.shtml) is not available.
.war file works perfectly on my workstation, but not working on mochahost.
Any ideas to solve it?
Thanks in advance.
Mochahost have a very good support, try livechatting with their tech department, you will probably have the thing solved.
That's what I do.
Make sure you update live site URL. For instance, generally, on local system you access web app as http://localhost:8080/myapp but, on server it changes to http://[www.]myapp.com. Again, this is just an instance. The point is, the live site must reflect correct URL from code (servlet/JSP/action/etc...) and configuration properties, if any.
Comment 'DirectoryIndex' property in .htaccess file if you do not have any index file.
Comment 'RewriteCond' property in .htaccess file if you do not have any rewrite requirement.
For sure, one of the reason - if client does not accept cookies and servlet does not encode URL.
Is there anything in the Servlet spec, Tomcat, or Wicket that will allow a webapp running behind mod_proxy to determine the non-proxied URL of the request?
We need to send out emails with links in them. I had been using the following bit of Wicket to construct URLs to specific pages in the app:
String relURL = RequestCycle.get().getRequest().getRelativePathPrefixToWicketHandler();
RequestUtils.toAbsolutePath(relURL);
Since the emails don't go back out through the proxy, of course the URLs don't get re-written, and end up looking like http://localhost/....
Right now the best I can do is to hard-code the URLs to our production server, but that's setting us up for some debugging headaches when running on dev/test machines.
Using InetAddress.getLocalHost().getHostName() isn't really a solution, since that's likely to return prod1.mydomain.com or somesuch, rather than mydomain.dom, from which the request likely originated.
As answered for the question Retain original request URL on mod_proxy redirect:
If you're running Apache >= 2.0.31 then you might try to set the
ProxyPreserveHost directive as described here .
This should pass the original Host header trough mod_proxy into your
application, and normally the request URL will be rebuild there (in
your Servlet container) using the Host header, so the schema location
should be build using the host and path infos from "before" the proxy.
Is there anything in the Servlet spec, Tomcat, or Wicket that will allow a webapp running behind mod_proxy to determine the non-proxied URL of the request?
No. If the reverse proxy doesn't put the information that you require into the message headers before passing them on, there's no way to recover it.
You need to look at the Apache Httpd documentation to figure out how to get the front-end to put the information that you need into the HTTP request headers on the way through. (It can be done. I just can't recall the details.)