0
votes

I have a spring boot application with context-path /services. The context-path entry in property file:

server.servlet.context-path=/services

When I use the URL http://localhost:8080/services/ with GET method, it is working fine and returning the static index.html file in response. But when I try to use the same URL http://localhost:8080/services/ with POST method, I am getting the following error:

{
    "timestamp": "2020-11-11T07:06:37.341+00:00",
    "status": 405,
    "error": "Method Not Allowed",
    "message": "",
    "path": "/services/"
}

I have tried using redirect-context-root property, but that did not help. I also tried server.servlet.context-path=/services/ - but this also did not help. What property or configuration will force spring framework to allow POST method for any request with context-path with a trailing slash (/) ?

From the logs, I can see the view is getting resolved to [view="forward:index.html"], but right after that we see the ERROR HttpRequestMethodNotSupportedException: Request method 'POST' not supported. So not able to understand which spring class is responsible for throwing this error? And how can we suppress this behavior?

o.s.s.web.util.matcher.OrRequestMatcher  : Trying to match using Ant [pattern='/rest/**']
o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/'; against '/rest/**'
o.s.s.web.util.matcher.OrRequestMatcher  : No matches found
o.s.web.servlet.DispatcherServlet        : POST "/services/", parameters={}
pertySourcedRequestMappingHandlerMapping : looking up handler for path: /
o.s.b.a.w.s.WelcomePageHandlerMapping    : Mapped to ParameterizableViewController [view="forward:index.html"]
o.s.s.w.header.writers.HstsHeaderWriter  : Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@363fa5d2
w.c.HttpSessionSecurityContextRepository : SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
.w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported]
o.s.web.servlet.DispatcherServlet        : Completed 405 METHOD_NOT_ALLOWED
1
which annotation do you have on your controller? GetMapping? the fact that you get 405 and not 404 means that the path is good and you get to the controller, you just need to tell it there to handle POST - Nir Levy
I don't have any controller mapping for this context-path/ path. All my RestController are having @PostMapping with specific value property. So I don't have any explicit controller for / path. - Rajib Biswas

1 Answers

0
votes

There is a spring issue reported: https://github.com/spring-projects/spring-framework/issues/22140. But spring also made it clear that they will not make any such change, since request to static resources should not be of type POST, as we are not trying to modify them, rather we are trying to GET them.

I was looking for a workaround, since I had to support POST at the context-root (because of SSO-IDP requirement). So I tried to replicate the 302 Redirect behavior in a Filter. In one of the filters, I checked for the request method POST, request URI /services/ and redirected the request to /services/. This converts the POST request into GET at path /services/ and it works.

// Inside doFilter() method of a Filter
if ("POST".equalsIgnoreCase(httpRequest.getMethod()) && "/services/".equalsIgnoreCase(httpRequest.getRequestURI())) {
    httpResponse.sendRedirect("/services/"); // This converts the POST request to GET request
    return;
}

After introducing this behavior in filter, when I POST a request to http://localhost:8080/services/, from the above filter, it gets redirected to http://localhost:8080/services/ using GET method and I get the desired index.html as response.