Вопрос

I have a simple method (running on Tomcat 6.0.35) that looks like so:

@RequestMapping(value = "/bla/d", method = RequestMethod.DELETE)
@ResponseStatus(HttpStatus.NO_CONTENT)
public void d(@RequestParam String d){
    //logic here
}

When I send a DELETE request with post like parameters (d=gggg in the body) I get a 400 Bad Request. But if I change it to

@RequestMapping(value = "/bla/d", method = RequestMethod.POST)
@ResponseStatus(HttpStatus.NO_CONTENT)
public void d(@RequestParam String d){
    //logic here
}

It works perfectly. I was using a Firefox Add-on to test it (and python and Spring's RestTemplate with same result) here's how the request look with POST(a is a cope pasted method named a with parameter a):

POST /bla/a HTTP/1.1
Host: ~~~~:8080
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:13.0) Gecko/20100101 Firefox/13.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Content-Length: 7
Pragma: no-cache
Cache-Control: no-cache
a=asdas

HTTP/1.1 204 No Content
Server: Apache-Coyote/1.1
Date: Tue, 12 Jun 2012 09:29:46 GMT

And delete looks like:

DELETE /bla/d HTTP/1.1
Host: ~~~~~:8080
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:13.0) Gecko/20100101 Firefox/13.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Content-Length: 7
d=asdas

HTTP/1.1 400 Bad Request
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=utf-8
Content-Length: 971
Date: Tue, 12 Jun 2012 09:30:04 GMT
Connection: close

Please help me, I might be missing something stupid but I just can't see it. My original problem was sending an array via post-like body with DELETE request but it seems that something more basic is wrong.

Это было полезно?

Решение

Well after doing some research and debugging I've found out that Spring's ServletWebREquest calls getParameterValues of org.apache.catalina.connector.RequestFacade.getParameterValues which calls getParameterValues in which I've found the following line (Request.java 2599-2600):

if (!getMethod().equalsIgnoreCase("POST"))
return;

Which kills any attempt to send POST-like parameters with DELETE which means Tomcat is actively restricts this use-case even though the RFC does not restrict such usage(although it does say that some existing implementations may reject such requests, Tomcat just throws it's parameters away). What brings one that's using Spring and Tomcat and trying to send a DELETE requests with parameters to ugly solutions like getting all the request body with @RequestBody and extracting it manually which makes your supposedly innocent method that just wants to delete something aware of some a Map that contains the request body.

@fmucar

Другие советы

I was having a similar issue and the resolution that I found was to add the fields in the query string. I would still like to know the reasons why a form body would be excluded in this way, but for now this is a work-around.

So for your example it would mean adding ?a=asdas to the Host: ~~~~~:8080 URL.

I am using spring-webmvc:3.2.4.RELEASE so I'm not sure if this will work in your version or not.

This is a pretty old post, but in case anyone else is looking for how to enable @RequestParam on DELETE methods, here's what I did on tomcat 8.5.4.

@Value("${server.parseBodyMethods}")
private String parseBodyMethods;

@Bean
public TomcatEmbeddedServletContainerFactory containerFactory() {
    return new TomcatEmbeddedServletContainerFactory() {
        protected void customizeConnector(Connector connector) {
            super.customizeConnector(connector);
            connector.setParseBodyMethods(parseBodyMethods);
        }
    };
}

Plug in 'POST,DELETE' to that customizer, and your delete request parameters should start working.

I found parseBodyMethods in org.apache.catalina.connector.Connector, and here is Tomcat's documentation on it:

This is useful in RESTful applications that want to support POST-style semantics for PUT requests. Note that any setting other than POST causes Tomcat to behave in a way that goes against the intent of the servlet specification. The HTTP method TRACE is specifically forbidden here in accordance with the HTTP specification. The default is POST (Source)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top