In Ruby/Rack, I'm able to get the scheme of the current request URL from scheme#request
. However, in Go, http.Request.URL.Scheme
returns an empty string:
package main
import (
"fmt"
"log"
"net/http"
)
func main() {
http.HandleFunc("/", handler)
log.Fatal(http.ListenAndServe(":8080", nil))
}
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "%#v\n", r.URL.Scheme) // Always shows empty string
}
How do I get scheme of the current request URL?
localhost is a special case for
URL
formation. It is going to be empty anyway if your client is localhost.net.http package doc:
The way to get required url/uri information is to get it from
http.Request
directly. For example:A quick
grep
shows thatr.URL.Scheme
is never set to anything other than the empty string anywhere innet/http
. Personally I think it should be, as far as possible, but apparently I have a minority opinion.If you opened a TLS listener yourself with
http.ListenAndServeTLS()
then presumably you know the scheme is https already. You can use a trivial middleware handler that fills inr.URL.Scheme
in this case.If you're running behind a web server, then it may pass the request protocol in a header such as
X-Forwarded-Proto
. In this case, you can use a handler like gorilla's handlers.ProxyHeaders() to fill in the missing fields.An example using gorilla mux:
From its comments:
It is because, you're accessing the HTTP server so:
in this cases, based on parsing what you get is raw URL from Go's http.Request.URL. why you are getting this is because you are 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 have to access the Host attribute of the http.Request struct. See http://golang.org/pkg/http/#Request
as it is not directly available, but you can still be able to assemble it:
Since you use
ListenAndServe
and notListenAndServeTLS
, your scheme can be safely assumed as http. If you use both tls and non tls versions, you can user.TLS
and check it for null to know whether TLS was established. If your go app is running behind a reverse proxy, then you have to check the documentation on the web server which is forwarding the requests to your app, to learn how to configure it to pass this information as headers. Here's a link describing nginx configuration which accomplishes that. You can easily find configuration guides for other webservers as well.Better yet, configure HSTS on your main web server, so that you don't have to worry about insecure connections altogether. There are very few, if any, legitimate uses to non-TLS http. For nginx you can find this article useful. And again for other web servers you will easily find configuration guides.
If you're unsure if your site/application needs https I recommend reading this.