2

I seem to get empty body content of a Go http.Request if the method is DELETE. But if I change the method to POST, then the body content gives me the content I expect.

The relevant code from my golang looks like this:

import(
  "github.com/gorilla/handlers"
  "github.com/gorilla/mux"
)
func Delete(w http.ResponseWriter, r *http.Request) {
  r.ParseForm()
  qs := r.Form
  log.Println(qs)
}


func main() {
  router := mux.NewRouter()

  router.HandleFunc("/profile", Delete).Methods("POST")
  router.HandleFunc("/profile", Delete).Methods("DELETE")

}

Now when I run this JavaScript code form my browser:

fetch(sendurl,{
  method:"POST",
  headers:{
    'Content-Type': 'application/x-www-form-urlencoded'
  },
  body:"data="+project.encodeFormURIComponent(JSON.stringify({"ids":[1032,1033]}))
})
.then(response=>{
  if(response.ok)
    return response.json();
})
.then(result=>{
  console.log(result);
})

I see a nice array of numbers in my qs[ids] in my Golang code. But if I change my method:"POST" to method:"DELETE" in the JavaScript, then qs is empty.

What am I doing wrong?


UPDATE

This JavaScript with the DELETE method can populate the Go qs variable the way one would normally expect:

fetch(sendurl+"?data="+project.encodeFormURIComponent(JSON.stringify({"ids":[1032,1033]})),{
  method:"DELETE",
  headers:{
    'Content-Type': 'application/x-www-form-urlencoded'
  }
})
.then(response=>{
  if(response.ok)
    return response.json();
})
.then(result=>{
  console.log(result);
})

So it seems Go will ignore JavaScript body argument when DELETE method is used, but it will respect the query string content in the API endpoint url? Why is it like that?

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
John
  • 32,403
  • 80
  • 251
  • 422
  • Can you confirm that the client/browser is sending the body? Do you have something in front of the go app, like a proxy? – mkopriva Nov 23 '19 at 19:58
  • In the network tab of my FireFox, I can see the body or params is being sent as `data {"ids":[6026,6024]}`. I didn't put anything in front of my golang app. All the POST and PUT statements have no trouble parsing the body. – John Nov 23 '19 at 20:02
  • 1
    This is actually hinted to by the documentation on the `Form` and `PostForm` fields ( https://github.com/golang/go/blob/3409ce39bfd7584523b7a8c150a310cea92d879d/src/net/http/request.go#L248-L253) Maybe try using the json as is, not as form-urlencoded, set the correct header for it in js, and parse the request's Body field using `encoding/json`? – mkopriva Nov 23 '19 at 20:11
  • And the documentation on the actual [`ParseForm`](https://github.com/golang/go/blob/3409ce39bfd7584523b7a8c150a310cea92d879d/src/net/http/request.go#L1239) method says *"For POST, PUT, and PATCH requests, it also parses the request body as a form and puts the results into both r.PostForm and r.Form. Request body parameters take precedence over URL query string values in r.Form."* – mkopriva Nov 23 '19 at 20:16

1 Answers1

3

https://www.rfc-editor.org/rfc/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 query string is part of the target-uri of the request; in other words, the query string is part of the identifier, not an incidental modifier of it. But the message-body of the request is not part of the identifier.

So your local framework, or any of the other general purpose components forwarding your request, are not required to provide support for the message-body.

Think "undefined behavior" in C.

Community
  • 1
  • 1
VoiceOfUnreason
  • 52,766
  • 5
  • 49
  • 91