Disable all default HTTP error response content in Tomcat
Solution 1
Although this doesn't respond exactly to the "not send anything" statement on the question, and on the wave of Clive Evans' answer, I found out that in tomcat you can make those too much verbose texts go away from error pages without creating a custom ErrorReportValve.
You can accomplish to this customizing ErrorReportValve through the 2 params "showReport" and "showServerInfo" on your "server.xml":
<Valve className="org.apache.catalina.valves.ErrorReportValve" showReport="false" showServerInfo="false" />
Link to official documentation.
Worked for me on tomcat 7.0.55, didn't work for me on tomcat 7.0.47 (I think because of something reported on the following link http://www.mail-archive.com/[email protected]/msg113856.html)
Solution 2
The quick, slightly dirty, but easy way of stopping Tomcat from sending any error body is to call setErrorReportValveClass against the tomcat host, with a custom error report valve which overrides report to do nothing. ie:
public class SecureErrorReportValve extends ErrorReportValve {
@Override
protected void report(Request request,Response response,Throwable throwable) {
}
}
and set it with:
((StandardHost) tomcat.getHost()).setErrorReportValveClass(yourErrorValveClassName);
If you want to send your message, and just think Tomcat shouldn't mess with it, you want something along the lines of:
@Override
protected void report(final Request request, final Response response, final Throwable throwable) {
String message = response.getMessage();
if (message != null) {
try {
response.getWriter().print(message);
response.finishResponse();
} catch (IOException e) {
}
}
}
Solution 3
Although it's Servlet spec compliant, for security reasons I don't want tomcat or any other Servlet container to send error details. I struggled with this as well a bit. After searching and trying, the solution can be summed up as:
- as others mentioned, don't use
sendError()
, usesetStatus()
instead (in Jersey framework you can choose) - frameworks like e.g. Spring Security use
sendError()
though... - write a
Filter
that
a. redirects calls tosendError()
tosetStatus()
b. flushes the response at the end to prevent the container from further modifying the response
A little example servlet filter doing this can be found here.
Solution 4
As Heikki said, setting the status instead of sendError()
causes the Tomcat not touch the response entity/body/payload.
If you only want to send the response headers without any entity, like in my case,
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentLength(0);
does the trick. With Content-Length: 0
, the print()
will have no effect even if used, like:
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentLength(0);
response.getWriter().print("this string will be ignored due to the above line");
the client receives something like:
HTTP/1.1 401 Unauthorized
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=utf-8
Content-Length: 0
Date: Wed, 28 Sep 2011 08:59:49 GMT
If you want to send some error message, use the setContentLength()
with message length (other than zero) or you can leave it to the server
Solution 5
Configure <error-page>
Elements in web.xml
Edit $CATALINA_HOME/conf/web.xml
, add at the end the following <error-page>
, save and restart tomcat
<web-app>
...
...
...
<error-page>
<error-code>404</error-code>
<location>/404.html</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/500.html</location>
</error-page>
<error-page>
<error-code>400</error-code>
<location>/400.html</location>
</error-page>
</web-app>
- It works great as I expect even though I didn't actually created a valid routes for those specified
location
values (e.g./400.html
)
before
after
Rob Hruska
Software Engineer for Hudl in Lincoln, NE. Come work with us!
Updated on September 07, 2021Comments
-
Rob Hruska over 2 years
By default, Tomcat sends some HTML content back to the client if it encounters something like an HTTP 404. I know that via
web.xml
an<error-page>
can be configured to customize this content.However, I'd just like for Tomcat to not send anything in terms of response content (I'd still like the status code, of course). Is there any way to easily configure this?
I'm trying to avoid A) explicitly sending empty content on the response stream from my Servlet, and B) configuring custom error pages for a whole bunch of HTTP error statuses in my
web.xml
.For some background, I'm developing an HTTP API and am controlling my own response content. So for an HTTP 500, for example, I'm populating some XML content on the response containing error information. For situations like an HTTP 404, the HTTP response status is sufficient for clients, and the content tomcat is sending is unnecessary. If there's a different approach, I'm open to hearing it.
Edit: After continued investigation, I still can't find much in the way of a solution. If someone can definitively say this is not possible, or provide a resource with evidence that it will not work, I'll accept that as an answer and try and work around it.
-
Rob Hruska about 15 yearsI mentioned in my question that I would like to avoid configuring error pages (even if they're empty) for a bunch of statuses. If it's my only option then I guess I'll have to - but I'm looking for alternatives.
-
mckamey over 11 yearsThis worked great! I like having a single place to control this rather than having to wrap every single response. More aspect-oriented.
-
Poni over 11 yearsIndeed a better solution! Thanks
-
Rob Hruska over 11 yearsCan you clarify what you mean by the behavior being "absolutely correct"? Which behavior, specifically? A link or excerpt from the Servlet specification may help. I couldn't find anything in the 3.0 specification that addressed requirements on the actual content of a response, particularly for error responses. As far as RFC2616 goes, there aren't any requirements on the entity content for any error statuses.
-
Michael-O over 11 yearsYes, of course. This is not bound to the RFC but to the Servlet spec itself. Check Servlet spec 3.0, chapters 10.9.2 and 10.9.3, Oracle's Servlet API JavaDocs for both
sendError
methods and my question to the Tomcat Users Mailinglist. -
Clive Evans over 11 yearsFeel free to point to the part of the spec that says you shouldn't take the Tomcat ErrorReportValve which rewrites your message into a message containing a whole load of information you probably don't want to share with the outside world, and instead, write just your message. I'm intrigued ...
-
Javier Esteban over 11 yearson another note, you can write your own ErrorValve and configure it in the server.xml's <Host> element: <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true" errorReportValveClass="security.MyErrorValveImpl"> see tomcat.apache.org/tomcat-7.0-doc/config/host.html
-
reallynice almost 10 yearsWell, more than a "quick, slightly dirt" answer, looks like the answer that really meets the needs.
-
eis over 8 yearsWorking with Tomcat 8. Excellent solution!
-
mjs over 8 yearsAnd now you application is tomcat dependant.
-
Clive Evans over 8 yearsIf you weren't using Tomcat, you wouldn't be suffering from Tomcat leaking your information ...
-
Night Owl almost 8 yearsThe Tomcat docs say the <Valve /> element can go within the <Engine />, <Host /> or <Context /> elements in server.xml. For me putting the valve within the <Engine /> element didn't work but putting it inside individual <Host /> elements did. The docs also say Tomcat routes any non matching host names to the <Host /> element that is set in the defaultHost attribute of the <Engine /> element. To ensure that URLs to locations outside of your hosts/contexts are not shown the error messages compiled into Tomcat you need to make sure this <Valve /> is added your default <Host />.
-
watery almost 8 years+1 for pointing out that frameworks have predefined behaviour and providing an example filter, which — as I'm using Jersey — made me discover a a specific Jersey property
-
John Yeary over 5 yearsI needed to add
try { response.finishResponse(); } catch (IOException e) { }
to the emptyreport()
method to prevent it from producing any output. -
maxxyme almost 5 yearsAbove link posted by @watery is dead as of 2019, correct link now is jersey.github.io/apidocs/latest/jersey/org/glassfish/jersey/…
-
maxxyme almost 5 yearsYou missed the point where the OP said he's trying to avoid [..] configuring custom error pages for a whole bunch of HTTP error statuses in [his] web.xml.
-
Jossef Harush Kadouri almost 5 yearsAgree. Yet its helpful for those who google their way for examples. This question have good SEO rating.
-
bluish over 2 yearsLink is dead again, better look at this answer ;)