HTTP Content-type header and body are not transmitted when sent from within PhantomJS

996 views Asked by At

When initiating an HTTP DELETE request with content-type header and body, these two elements are:

  • Well received when the request is initiated from within Chrome,
  • Not received when the request is initiated from within PhantomJS.

Which of the two is behaving as per the standard?

It is to be noted that in both cases, the client and the server are the same.

Below are the logs of the request at the server level.

Log of the request sent from within PhantomJS

SERVER: -------------------------------------------------------
SERVER: - R E Q U E S T                                       -
SERVER: -------------------------------------------------------
SERVER: req.url      /test/del
SERVER: req.method   OPTIONS
SERVER: req.headers  { 'access-control-request-method': 'DELETE',
  origin: 'http://localhost:9876',
  'user-agent': 'Mozilla/5.0 (Unknown; Linux x86_64) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.7 Safari/534.34',
  referer: 'http://localhost:9876/context.html',
  'access-control-request-headers': 'Content-Type, Accept',
  accept: '*/*',
  connection: 'Keep-Alive',
  'accept-encoding': 'gzip',
  'accept-language': 'fr-FR,en,*',
  host: 'localhost:9009' }
SERVER: req.query    {}
SERVER: req.body     {}
SERVER: -------------------------------------------------------
SERVER: -------------------------------------------------------
SERVER: - R E S P O N S E                                     -
SERVER: -------------------------------------------------------
SERVER: res.headers  { 'Access-Control-Allow-Headers': 'Origin, X-Requested-With, Content-Type, Accept',
  'Access-Control-Allow-Methods': 'PUT, DELETE',
  'Access-Control-Allow-Origin': '*' }
SERVER: -------------------------------------------------------
127.0.0.1 - - [Thu, 13 Nov 2014 16:07:08 GMT] "OPTIONS /test/del HTTP/1.1" 200 - "http://localhost:9876/context.html" "Mozilla/5.0 (Unknown; Linux x86_64) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.7 Safari/534.34"
SERVER: -------------------------------------------------------
SERVER: - R E Q U E S T                                       -
SERVER: -------------------------------------------------------
SERVER: req.url      /test/del
SERVER: req.method   DELETE
SERVER: req.headers  { origin: 'http://localhost:9876',
  'user-agent': 'Mozilla/5.0 (Unknown; Linux x86_64) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.7 Safari/534.34',
  accept: 'application/json, application/json;q=0.8, text/plain;q=0.5, */*;q=0.2',
  referer: 'http://localhost:9876/context.html',
  connection: 'Keep-Alive',
  'accept-encoding': 'gzip',
  'accept-language': 'fr-FR,en,*',
  host: 'localhost:9009' }
SERVER: req.query    {}
SERVER: req.body     {}
SERVER: -------------------------------------------------------
SERVER: -------------------------------------------------------
SERVER: - R E Q U E S T                                       -
SERVER: -------------------------------------------------------
SERVER: req.url      /del
SERVER: req.method   DELETE
SERVER: req.headers  { origin: 'http://localhost:9876',
  'user-agent': 'Mozilla/5.0 (Unknown; Linux x86_64) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.7 Safari/534.34',
  accept: 'application/json, application/json;q=0.8, text/plain;q=0.5, */*;q=0.2',
  referer: 'http://localhost:9876/context.html',
  connection: 'Keep-Alive',
  'accept-encoding': 'gzip',
  'accept-language': 'fr-FR,en,*',
  host: 'localhost:9009' }
SERVER: req.query    {}
SERVER: req.body     {}
SERVER: -------------------------------------------------------
SERVER: -------------------------------------------------------
SERVER: - R E S P O N S E                                     -
SERVER: -------------------------------------------------------
SERVER: res.headers  { 'Content-type': 'application/json',
  'Access-Control-Allow-Origin': '*' }
SERVER: res.body     { code: 'Declined',
  reason: 'UNEXPECTED CONTENT',
  message: 'The content-type "undefined" is unexpected. Please use "application/json".' }
SERVER: -------------------------------------------------------

Log of the request sent from within Chrome

SERVER: -------------------------------------------------------
SERVER: - R E Q U E S T                                       -
SERVER: -------------------------------------------------------
SERVER: req.url      /test/del
SERVER: req.method   OPTIONS
SERVER: req.headers  { host: 'localhost:9009',
  connection: 'keep-alive',
  'access-control-request-method': 'DELETE',
  origin: 'http://localhost:9876',
  'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36',
  'access-control-request-headers': 'accept, content-type',
  accept: '*/*',
  referer: 'http://localhost:9876/context.html',
  'accept-encoding': 'gzip,deflate,sdch',
  'accept-language': 'en-US,en;q=0.8' }
SERVER: req.query    {}
SERVER: req.body     {}
SERVER: -------------------------------------------------------
SERVER: -------------------------------------------------------
SERVER: - R E S P O N S E                                     -
SERVER: -------------------------------------------------------
SERVER: res.headers  { 'Access-Control-Allow-Headers': 'Origin, X-Requested-With, Content-Type, Accept',
  'Access-Control-Allow-Methods': 'PUT, DELETE',
  'Access-Control-Allow-Origin': '*' }
SERVER: -------------------------------------------------------
127.0.0.1 - - [Thu, 13 Nov 2014 16:15:04 GMT] "OPTIONS /test/del HTTP/1.1" 200 - "http://localhost:9876/context.html" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36"
SERVER: -------------------------------------------------------
SERVER: - R E Q U E S T                                       -
SERVER: -------------------------------------------------------
SERVER: req.url      /test/del
SERVER: req.method   DELETE
SERVER: req.headers  { host: 'localhost:9009',
  connection: 'keep-alive',
  'content-length': '23',
  accept: 'application/json, application/json;q=0.8, text/plain;q=0.5, */*;q=0.2',
  origin: 'http://localhost:9876',
  'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36',
  'content-type': 'application/json',
  referer: 'http://localhost:9876/context.html',
  'accept-encoding': 'gzip,deflate,sdch',
  'accept-language': 'en-US,en;q=0.8' }
SERVER: req.query    {}
SERVER: req.body     { field1: 1, field2: 2 }
SERVER: -------------------------------------------------------
SERVER: -------------------------------------------------------
SERVER: - R E Q U E S T                                       -
SERVER: -------------------------------------------------------
SERVER: req.url      /del
SERVER: req.method   DELETE
SERVER: req.headers  { host: 'localhost:9009',
  connection: 'keep-alive',
  'content-length': '23',
  accept: 'application/json, application/json;q=0.8, text/plain;q=0.5, */*;q=0.2',
  origin: 'http://localhost:9876',
  'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36',
  'content-type': 'application/json',
  referer: 'http://localhost:9876/context.html',
  'accept-encoding': 'gzip,deflate,sdch',
  'accept-language': 'en-US,en;q=0.8' }
SERVER: req.query    {}
SERVER: req.body     { field1: 1, field2: 2 }
SERVER: -------------------------------------------------------
SERVER: -------------------------------------------------------
SERVER: - R E S P O N S E                                     -
SERVER: -------------------------------------------------------
SERVER: res.headers  { 'Content-type': 'application/json',
  'Access-Control-Allow-Origin': '*' }
SERVER: res.body     { code: 'Accepted' }
SERVER: -------------------------------------------------------
1

There are 1 answers

2
Artjom B. On BEST ANSWER

The RFC 2616 for HTTP/1.1 specifies the DELETE method in chapter 9.7. It does not specify anything about the enclosed entity (message body) in the description text which it does for POST and PUT.

From your logs it is apparent that PhantomJS doesn't even send the message body and therefore doesn't need to include the content type, because it assumes that it will never be used anyway as it is not defined. It seems that Chrome sends the message body regardless.

There is a draft for an update which includes the following text in chapter 6.7:

Bodies on DELETE requests have no defined semantics. Note that sending a body on a DELETE request might cause some existing implementations to reject the request.

Since PhantomJS 1.x is based on a more than three year old version of WebKit (pre-draft), it behaves this way. Chrome on the other hand may have implemented the proposed draft and actively sends the body on DELETE requests. See this question for more information.

If your operation depends on the message body for the DELETE method, you should change the implementation so that the resource which you delete is completely defined by the URI.