Servlets 3.1: how to handle body in DELETE request

I am writing a server for handling http requests from a javascript annotation package (annotatorjs.org). The javascript sends an HTTP DELETE request to the server that includes the id of the object in the path, and also sends the annotation in the body of the request in a JSON object.

I've tried implementing the DELETE request both with a Java Web Services object, and a plain servlet. In both cases, when I make the request without a body, it works, but when I add a body, I get a 400 Bad Request.

Here is my servlet

@WebServlet("/api/store/delete/*") public class AnnotatorServlet extends HttpServlet { @Override protected void doDelete( HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("received DELETE request,requestURI="+request.getRequestURI()); } }

My curl command, without body succeeds:

curl -i -X DELETE http://localhost:8080/text/api/store/delete/555608203004e74adbf65343 HTTP/1.1 200 OK Server: GlassFish Server Open Source Edition 4.1 X-Powered-By: Servlet/3.1 JSP/2.3 (GlassFish Server Open Source Edition 4.1 Java/Oracle Corporation/1.8) Date: Tue, 19 May 2015 19:35:08 GMT Content-Length: 0

My curl command with body fails:

curl -i -X DELETE -d @test.json http://localhost:8080/text/api/store/delete/555608203004e74adbf65343 HTTP/1.1 400 Bad Request Server: GlassFish Server Open Source Edition 4.1 X-Powered-By: Servlet/3.1 JSP/2.3 (GlassFish Server Open Source Edition 4.1 Java/Oracle Corporation/1.8) Date: Tue, 19 May 2015 19:35:16 GMT Connection: close Content-Length: 0


DELETE is not supposed to have a body, just like GET.

RFC: http://tools.ietf.org/html/rfc7231#section-4.3.5

A payload within a DELETE request message has no defined semantics; sending a payload body on a DELETE request might cause some existing implementations to reject the request.

The best practice is, just don't do it.


One could argue that, this is a bug in the server. But the server could also legitimately claim that, this is a rare situation that it has the right to refuse to serve.


Since the DELETE method explicitly does not define a payload (RFC 7231 section 4.3.5), the relevant guideline it should be following is RFC 7230 section 3.3:

The presence of a message body in a request is signaled by a Content-Length or Transfer-Encoding header field. Request message framing is independent of method semantics, even if the method does not define any use for a message body.

The proper standards compliant behaviour for the server is to either consume and ignore the payload, or to act on it in some API specific way. That "API specific way" may be sending 400 or any other status code.

That second curl test you are using does not appear to send any JSON data to the API. When I run it just sends the test string "test.json" as the payload. So it is not clear what the server is rejecting (payload existence? or unknown payload format?).

If you can devise a test which properly demonstrates that the server is rejecting on the mere existence of payload, then you should file a bug against the server.


The Response for the second curl command contains Content-Length:0

I think the request made by the curl, is sending Request property of Content-Length incorrectly.


  • Identifying path of current JSF / XHTML page [duplicate]
  • RequestMapping issue with multiple Angular clients in Spring Boot Application
  • Why I can't make HttpWebRequest working with NTLM authentication
  • Hanfire not logging custom exception with metadata
  • Spring Security SAML with PingIdentity/ PingFederation
  • Json data is not binding to jqgrid
  • PHP/mysqli: Inserting IP address with mysqli_stmt_bind_param()
  • Setting up Let's encrypt with Go - handshake errors
  • Cuda Mutex, why deadlock?
  • Callback, specified in QueueUserAPC , does not get called
  • Internet explorer and google chrome frame can support webRTC?
  • How to add definitions for cuda source code in cmake
  • Pattern combining type test and literal
  • Behaviour of System.Timer when Interval property changed
  • problem with classes not found during PlayPlugin.enhance
  • Runtime error in UVA Online Judge [closed]
  • 3.0.0.M1: SSL - Invalid keystore format
  • If statement skipping right to else after being called once?
  • How to copy styled text in JTextPane
  • Pass Dictionary to Javascript array
  • Reading a file into a multidimensional array
  • Button text different than value submitted in query string
  • Odoo 10 - Overriding unlink method
  • App restarts from wrong activity
  • Make VS2015 use angular-cli ng at build time in a .NET project
  • How to test if a URL from an Eclipse bundle is a directory?
  • why do I get the error when installing the gem 'pg'? [duplicate]
  • Jetty Server not starting: Unable to establish loopback connection
  • Jenkins: How To Build multiple projects from a TFS repository?
  • How do I fake an specific browser client when using Java's Net library?
  • Updating server-side rendering client-side
  • Validaiting emails with Net.Mail MailAddress
  • sending/ receiving email in Java
  • Timeout for blocking function call, i.e., how to stop waiting for user input after X seconds?
  • Apache 2.4 - remove | delete | uninstall
  • Run Powershell script from inside other Powershell script with dynamic redirection to file
  • Windows forms listbox.selecteditem displaying “System.Data.DataRowView” instead of actual value
  • Proper folder structure for lots of source files
  • Proper way to use connect-multiparty with express.js?
  • How does Linux kernel interrupt the application?