Skip to content

net/http: redirect code is not handled for DELETE requests.  #13994

Closed
@harshavardhana

Description

@harshavardhana

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    FeatureRequestIssues asking for a new feature that does not need a proposal.FrozenDueToAgeNeedsFixThe path to resolution is known, but the work has not been done.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions