In order to disable insecure http methods, I have used a request filter
@Component
public class MethodFilter extends OncePerRequestFilter {
private final String[] allowedMethods = new String[]{"PUT", "POST", "GET", "OPTIONS"};
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
if (Arrays.stream(allowedMethods).noneMatch(x -> x.equals(request.getMethod()))) {
response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
}
filterChain.doFilter(request, response);
}
}
This works perfectly for all methods except "TRACE". For trace method, this filter is not invoked and I get a echo back of the all the headers in response body
TRACE /error HTTP/1.1
my-header: test
accept: */*
host: localhost:8087
accept-encoding: gzip, deflate, br
connection: keep-alive
For all other methods which are not in the list I get result as expected
{
"timestamp": "2021-11-03T11:49:48.545+0000",
"status": 405,
"error": "Method Not Allowed",
"message": "DELETE method is not allowed",
"path": "/test"
}
Referring to doc it seems, trace requests are sent to frameworkservlet and processed there itself. Have tried setting spring.mvc.dispatch-trace-request=true
but now the responses are clubbed like this (filter still not invoked)
{
"timestamp": "2021-11-03T11:49:48.545+0000",
"status": 405,
"error": "Method Not Allowed",
"message": "TRACE method is not allowed",
"path": "/test"
}TRACE /error HTTP/1.1
my-header: test
accept: */*
host: localhost:8087
accept-encoding: gzip, deflate, br
connection: keep-alive
My question is how can I make TRACE response as same as the other requests ?
Note: The solution in this thread did not work for me.
Edit: Found the solution. An interceptor does the trick instead of a filter
@Component
public class MethodInterceptor implements HandlerInterceptor {
private final String[] allowedMethods = new String[]{"PUT", "POST", "GET", "OPTIONS"};
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (Arrays.stream(allowedMethods).noneMatch(x -> x.equals(request.getMethod()))) {
response.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
response.setHeader("Allow", "PUT, POST, GET, OPTIONS");
response.setContentType("message/http");
response.getWriter().println(request.getMethod() + " method not allowed");
response.getWriter().flush();
return false;
}
return true;
}
}
And add the interceptor via config file
@Configuration
public class InterceptorConfiguration implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MethodInterceptor());
}
}
This needs to be used in conjunction with spring.mvc.dispatch-trace-request=true