Bug 56568

Summary: Incompatible change in "JSPs only permit GET POST or HEAD"
Product: Tomcat 8 Reporter: Grigory <gkislin>
Component: JasperAssignee: Tomcat Developers Mailing List <dev>
Status: RESOLVED FIXED    
Severity: normal    
Priority: P2    
Version: 8.0.1   
Target Milestone: ----   
Hardware: All   
OS: All   

Description Grigory 2014-05-27 10:28:42 UTC
Since JSP 2.3 (Tomcat 8) only supported method for JSP is GET POST or HEAD:

https://jcp.org/aboutJava/communityprocess/maintenance/jsr245/245-MR3.html http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/servlet/JspServlet.java?view=diff&r1=1497877&r2=1497878&pathrev=1497878

But, I suppose, it is a big incompatible change as, for example, for exception handler it is used to forward to JSP for rendering exception and iso JSP view since JSP 2.3 response is:

Method Not Allowed
HTTP Status 405 - JSPs only permit GET POST or HEAD 

description The specified HTTP method is not allowed for the requested resource.
Apache Tomcat/8.0.3

If we use REST and Spring HandlerExceptionResolver in case of exception we bump into this problem for sure. Are there any workaround for this problem (iso change http method type)?


http://stackoverflow.com/questions/23886941/http-status-405-jsps-only-permit-get-post-or-head
Comment 2 Mark Thomas 2014-05-27 22:11:06 UTC
My original proposal [1] included a page directive to make this configurable. That part was rejected.

Options at this point:
1. Go ahead and add the page directive anyway 
2. Add an init param to the JSP Servlet to control the default methods supported
3. Check the method via an over-ridable method that could be over-riden by invididual JSPs.
4. Do 2 & 3.
5. Skip the method check if the JSP is an error page.

I stil think that the page directive is the way to handle this but I'd really like to do that with support from the JSP EG. Is 5 a sufficient solution for now? Can you think of any other use cases that might break because of this change?

[1] https://java.net/jira/browse/JSP-33
Comment 3 Konstantin Kolinko 2014-05-27 23:13:36 UTC
The specification requirement is not to reject, but to provide "undefined behaviour". The rejection behaviour is a security hardening.

(In reply to Mark Thomas from comment #2)

> 3. Check the method via an over-ridable method that could be over-riden
> by invididual JSPs.

I think implementing "3." means that the check is moved from org.apache.jasper.servlet.JspServlet#service(...)
into 
org.apache.jasper.runtime.HttpJspBase#service(...)

In this case there may be an alternative base class e.g. "AnyMethodHttpJspBase" and the JSP pages may be patched to use
<%page extends="o.a.j.runtime.AnyMethodHttpJspBase" %>

This strikes me as ugly / hacky.

> 2. Add an init param to the JSP Servlet to control the default methods supported

Maybe. As a regexp?
Comment 4 Mark Thomas 2014-06-05 14:18:36 UTC
I'm leaning towards 5. but remain tempted by 1.
Comment 5 Konstantin Kolinko 2014-06-05 14:26:36 UTC
The "5." means a JSP page that is served with ServletRequest.getDispatcherType() == DispatcherType.ERROR ?

There is also an option to interpret that as <%@page isErrorPage="true"%>.
Comment 6 Mark Thomas 2014-06-05 14:55:11 UTC
(In reply to Konstantin Kolinko from comment #5)
> The "5." means a JSP page that is served with
> ServletRequest.getDispatcherType() == DispatcherType.ERROR ?

This looks to be the easiest solution.

Mark
Comment 7 Konstantin Kolinko 2014-06-05 15:27:25 UTC
(In reply to Mark Thomas from comment #6)

OK.
Maybe also allow for DispatcherType.INCLUDE ?

If I remember correctly, Spring (as an example of an MVC framework) allows to switch view rendering from one using forward to one using include with a single boolean option. If it is an INCLUDE it means that the request has already been handled somehow, so it is likely safe for the JSP page to handle it.
Comment 8 Mark Thomas 2014-06-05 15:28:29 UTC
This specific issue (JSPs and error pages) has been fixed in 8.0.x for 8.0.9 onwards. The broader problem is still with the JSP EG.
Comment 9 Mark Thomas 2014-06-05 15:31:41 UTC
(In reply to Konstantin Kolinko from comment #7)
> (In reply to Mark Thomas from comment #6)
> 
> OK.
> Maybe also allow for DispatcherType.INCLUDE ?
> 
> If I remember correctly, Spring (as an example of an MVC framework) allows
> to switch view rendering from one using forward to one using include with a
> single boolean option. If it is an INCLUDE it means that the request has
> already been handled somehow, so it is likely safe for the JSP page to
> handle it.

Hmm. Not sure. Let's wait and see if anyone hits this issue before the EG makes a decision. The Spring developers and I share an employer so if there were issues here I'd have expected to have been asked to fix them by now.
Comment 10 Grigory 2014-06-09 13:05:36 UTC
Hello.
Vote for 5.) easiest solution.
I suppose this incompatibility prevent from switch to Tomcat 8 and need be fixed asap. Afterwards it could be expand for possible other cases.
Comment 11 Mark Thomas 2014-06-09 13:11:00 UTC
Restore the status to FIXED.
Comment 12 Grigory 2014-07-10 18:11:52 UTC
UPDATE: As of Tomcat 8.0.9 when a JSP is used to generate an error page, any HTTP method will be allowed.
Good news, thanks!
Comment 13 Grigory 2014-07-20 15:26:33 UTC
Hello Mark.
Sorry for late question: I only now install Tomcat 8.09 I try my case: redirect via org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver implementation to exception.jsp with HTTP DELETE.

In case of 
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
jsp is ignored.

Set <%@page isErrorPage="true"%> inside jsp doesn't help from

Method Not Allowed
HTTP Status 405 - JSPs only permit GET POST or HEAD

How can tell Tomcat that treat this jsp as error page?
Comment 14 Grigory 2014-08-19 11:51:47 UTC
Hello.
I use Tomcat 8.09 and redirect DELETE to JSP (via Spring @ExceptionHandler)

JSP header:

<%@page isErrorPage="true" contentType="application/json" pageEncoding="UTF-8" %>

Result is HTTP Status 405 - JSPs only permit GET POST or HEAD
Comment 15 Mark Thomas 2014-08-26 14:31:41 UTC
I've added an additional check for isErrorPage. Will be in 8.0.12 onwards.