Closed
Description
redirection is only handled for GET, HEAD, PUT and POST requests. But not for 'DELETE' , this leads to an issue where in a 'DELETE' request with proper response from the server doesn't honor redirect.
Following code reproduces this problem.
$ cat server.go
package main
import (
"fmt"
"log"
"net/http"
)
func main() {
http.HandleFunc("/bucket/redirect", func(w http.ResponseWriter, r *http.Request) {
msg := fmt.Sprintf("Successful redirect. for method %s", r.Method)
w.Write([]byte(msg))
})
http.HandleFunc("/bucket", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Location", "http://localhost:8080/bucket/redirect")
w.WriteHeader(http.StatusTemporaryRedirect)
})
log.Fatal(http.ListenAndServe(":8080", nil))
}
$ cat client.go
package main
import (
"bytes"
"fmt"
"log"
"net/http"
)
func main() {
clnt := &http.Client{}
req, err := http.NewRequest("GET", "http://localhost:8080/bucket", nil)
if err != nil {
log.Fatalln(err)
}
resp, err := clnt.Do(req)
if err != nil {
log.Fatalln(err)
}
// Write response.
var bufferGet bytes.Buffer
resp.Write(&bufferGet)
fmt.Println("--- GET RESPONSE ---")
fmt.Println(string(bufferGet.Bytes()))
fmt.Println("")
req, err = http.NewRequest("DELETE", "http://localhost:8080/bucket", nil)
if err != nil {
log.Fatalln(err)
}
resp, err = clnt.Do(req)
if err != nil {
log.Fatalln(err)
}
// Write response.
var bufferDelete bytes.Buffer
resp.Write(&bufferDelete)
fmt.Println("--- DELETE RESPONSE ---")
fmt.Println(string(bufferDelete.Bytes()))
}
Now running this client against the server.go
$ go run client.go
--- GET RESPONSE ---
HTTP/1.1 200 OK
Content-Length: 35
Content-Type: text/plain; charset=utf-8
Date: Mon, 18 Jan 2016 09:33:21 GMT
Successful redirect. for method GET
--- DELETE RESPONSE ---
HTTP/1.1 307 Temporary Redirect
Content-Type: text/plain; charset=utf-8
Date: Mon, 18 Jan 2016 09:33:21 GMT
Location: http://localhost:8080/bucket/redirect
Content-Length: 0
The problem seems to be in client.Do()
func (c *Client) Do(req *Request) (resp *Response, err error) {
method := valueOrDefault(req.Method, "GET")
if method == "GET" || method == "HEAD" {
return c.doFollowingRedirects(req, shouldRedirectGet)
}
if method == "POST" || method == "PUT" {
return c.doFollowingRedirects(req, shouldRedirectPost)
}
return c.send(req, c.deadline())
}
Is there a specific reason why DELETE is not handled?.
Tested with curl seems to work fine
$ curl -i -L -X DELETE localhost:8080/bucket
HTTP/1.1 307 Temporary Redirect
Location: http://localhost:8080/bucket/redirect
Date: Mon, 18 Jan 2016 09:39:00 GMT
Content-Length: 0
Content-Type: text/plain; charset=utf-8
HTTP/1.1 200 OK
Date: Mon, 18 Jan 2016 09:39:00 GMT
Content-Length: 38
Content-Type: text/plain; charset=utf-8
Successful redirect. for method DELETE
Also verified in RFC7231 - https://tools.ietf.org/html/rfc7231#section-4.3.5, doesn't talk anything specific about redirects for 'DELETE'.
Thanks for your inputs.