New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

net/http: request.Method is wrong when path start by // #29584

Open
Eraac opened this Issue Jan 5, 2019 · 2 comments

Comments

Projects
None yet
3 participants
@Eraac
Copy link

Eraac commented Jan 5, 2019

What version of Go are you using (go version)?

$ go version
go version go1.11.4 darwin/amd64

Does this issue reproduce with the latest release?

yes

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/kevin/Library/Caches/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/kevin/code/go"
GOPROXY=""
GORACE=""
GOROOT="/usr/local/Cellar/go/1.11.4/libexec"
GOTMPDIR=""
GOTOOLDIR="/usr/local/Cellar/go/1.11.4/libexec/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/Users/kevin/code/go/src/gitlab.com/cyclesinfos/consumer/station-state/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/43/45xhjfkn0xbbr4flsgzh879h0000gn/T/go-build866475413=/tmp/go-build -gno-record-gcc-switches -fno-common"

What did you do?

send post request with url start with two // (tbh it's was a mistake)

What did you expect to see?

server receive a post request

What did you see instead?

server receive a get request

Code

package main

import (
	"fmt"
	"net/http"
	"net/http/httputil"
	"time"
)

func main() {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Printf("method: %s\n", r.Method)
	})

	go func(){_ = http.ListenAndServe(":8080", http.DefaultServeMux)}()

	client := http.Client{Timeout: time.Second}
	req, _ := http.NewRequest(http.MethodPost, "http://localhost:8080//route", nil)
	_, _ = client.Do(req)

	time.Sleep(time.Millisecond * 500)

	bs, _ := httputil.DumpRequest(req, false)
	fmt.Printf("\n----\n%s", string(bs))
}

Output

method: GET

----
POST //route HTTP/1.1
Host: localhost:8080

@agnivade agnivade added this to the Go1.13 milestone Jan 6, 2019

@agnivade

This comment has been minimized.

Copy link
Member

agnivade commented Jan 6, 2019

/cc @bradfitz

@Gnouc

This comment has been minimized.

Copy link
Contributor

Gnouc commented Jan 6, 2019

@Eraac With this patch:

diff --git a/src/net/http/server.go b/src/net/http/server.go
index aa9c3f5d2e..88f53ff5ac 100644
--- a/src/net/http/server.go
+++ b/src/net/http/server.go
@@ -2336,7 +2336,11 @@ func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string) {
                _, pattern = mux.handler(host, path)
                url := *r.URL
                url.Path = path
-               return RedirectHandler(url.String(), StatusMovedPermanently), pattern
+               status := StatusMovedPermanently
+               if r.Method != "GET" || r.Method != "HEAD" {
+                       status = StatusTemporaryRedirect
+               }
+               return RedirectHandler(url.String(), status), pattern
        }
 
        return mux.handler(host, r.URL.Path)

You will get expected result.

But IMHO, we should return 500 error with a message like redirect with form data without user interaction won't be perform. HTTP spec requires response to a request other than GET or HEAD, the user agent MUST NOT automatically redirect the request unless it can be confirmed by the user

How do you think @bradfitz ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment