Get scheme of the current request URL
在Ruby / Rack中,我可以从
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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\ ", r.URL.Scheme) // Always shows empty string } |
如何获取当前请求URL的方案?
快速
如果您使用
1 2 3 4 5 6 7 | func AlwaysHTTPS(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { r.URL.Scheme ="https" next.ServeHTTP(w, r) }) } |
如果您在Web服务器后面运行,则它可能在标头(例如
使用大猩猩复用器的示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | package main import ( "log" "net/http" "github.com/gorilla/handlers" "github.com/gorilla/mux" ) func main() { r := mux.NewRouter() r.Use(handlers.ProxyHeaders) http.Handle("/", r) log.Fatal(http.ListenAndServe("[::]:8009", nil)) } |
来自其评论:
ProxyHeaders inspects common reverse proxy headers and sets the corresponding fields in the HTTP request struct. These are X-Forwarded-For and X-Real-IP for the remote (client) IP address, X-Forwarded-Proto or X-Forwarded-Scheme for the scheme (http|https) and the RFC7239 Forwarded header, which may include both client IPs and schemes.
NOTE: This middleware should only be used when behind a reverse proxy like nginx, HAProxy or Apache. Reverse proxies that don't (or are configured not to) strip these headers from client requests, or where these headers are accepted"as is" from a remote client (e.g. when Go is not behind a proxy), can manifest as a vulnerability if your application uses these headers for validating the 'trustworthiness' of a request.
由于使用的是
更好的是,在主Web服务器上配置HSTS,这样您就不必担心完全不安全的连接。非TLS http的合法使用(如果有的话)很少。对于nginx,您可以找到这篇文章有用。对于其他Web服务器,您又可以轻松找到配置指南。
如果不确定您的站点/应用程序是否需要https,建议阅读此内容。
为了提供http和https,您将需要同时调用这两个serve函数
因为如果您只使用其中的一种(如问题示例),那么您只会在1个协议
并且因为https是基于TLS的HTTP,所以
如果请求是通过https发出的,则不会为零,
如果请求是通过http发出的,则
因为使用TLS发出请求的唯一方法是使用https协议
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | func handler(w http.ResponseWriter, r *http.Request) { if r.TLS == nil { // the scheme was http } else { // the scheme was https } } func main() { http.HandleFunc("/", handler) go func(){ log.Fatal(http.ListenAndServeTLS(":8443","localhost.crt","localhost.key", nil)) }() log.Fatal(http.ListenAndServe(":8080", nil)) } |
localhost是
net.http软件包doc:
As a special case, if req.URL.Host is"localhost" (with or without a port number), then a nil URL and nil error will be returned.
获取必需的url / uri信息的方法是直接从
1 2 3 4 | func handler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w,"%s\ ", r.Host) } |
http标头X-Forwarded-Proto将具有http或https
这是因为您正在访问HTTP服务器,因此:
1 2 | GET / HTTP/1.1 Host: localhost:8080 |
在这种情况下,
基于解析您从Go的http.Request.URL获得的原始URL。之所以这样,是因为您正在从相对路径访问URL,因此URL对象中缺少主机或方案。
如果确实要获取HTTP主机,则可能必须访问http.Request结构的Host属性。参见http://golang.org/pkg/http/#Request
,因为它不是直接可用的,但是您仍然可以组装它:
1 2 3 4 | u := r.URL // The scheme can be http/https because that's depends on protocol your server handles. u.Scheme ="http" |