Why are request.URL.Host and Scheme blank in the development server?
Asked Answered
G

1

37

I'm very new to Go. Tried this first hello, world from the documentation, and wanted to read the Host and Scheme from the request:

package hello

import (
    "fmt"
    "http"
)

func init() {
    http.HandleFunc("/", handler)
}

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "Host: " + r.URL.Host + " Scheme: " + r.URL.Scheme)
}

But their values are both blank. Why?

Guinn answered 1/8, 2011 at 13:26 Comment(0)
P
60

Basically, since you're accessing the HTTP server not from an HTTP proxy, a browser can issue a relative HTTP request, like so:

GET / HTTP/1.1
Host: localhost:8080

(Given that, of course, the server is listening on localhost port 8080).

Now, if you were accessing said server using a proxy, the proxy may use an absolute URL:

GET http://localhost:8080/ HTTP/1.1
Host: localhost:8080

In both cases, what you get from Go's http.Request.URL is the raw URL (as parsed by the library). In the case you're getting, you're accessing the URL from a relative path, hence the lack of a Host or Scheme in the URL object.

If you do want to get the HTTP host, you may want to access the Host attribute of the http.Request struct. See http://golang.org/pkg/http/#Request

You can validate that by using netcat and an appropriately formatted HTTP request (you can copy the above blocks, make sure there's a trailing blank line after in your file). To try it out:

cat my-http-request-file | nc localhost 8080

Additionally, you could check in the server/handler whether you get a relative or absolute URL in the request by calling the IsAbs() method:

isAbsoluteURL := r.URL.IsAbs()
Palpate answered 2/8, 2011 at 11:55 Comment(5)
Interesting. Thanks for being so detailed. It is a little weird nevertheless that those are not present while using the dev server (I'd guess that the development server would setup some kind of host environment to fill the request). request.Host did work but to use URL.Scheme I'll need to check conditionally if the dev server is being used or not.Guinn
Thanks for the answer! Could you tell how to prevent this behaviour (headache for URL parsing)? Because I even can't get the scheme from the Request object :( Is this normal?Zito
It's worth noting that sometimes you can spot bots this way (they use the full URL when requesting a page).Spinster
You can tell https from http using the attribute r.TLS. If it's http, r.TLS == nil is false, while in https it's true. Source: 01happy.com/golang-get-full-urlSilverstein
This is not really true. I'm using a request with an absolute path including scheme (ws://). And the Scheme field is also empty. @navigaid This will also be true in case of wss scheme, so it's insufficient to match https only requests,Doglike

© 2022 - 2024 — McMap. All rights reserved.