Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Go中从http重写/重定向到https?_Go - Fatal编程技术网

如何在Go中从http重写/重定向到https?

如何在Go中从http重写/重定向到https?,go,Go,我已经建立了TLS,它可以正常工作。我知道如何在nginx中从http重写为https,但我不再使用nginx了。我不知道该怎么做才能正常进行 func main() { certificate := "/srv/ssl/ssl-bundle.crt" privateKey := "/srv/ssl/mykey.key" http.HandleFunc("/", rootHander) // log.Fatal(http.ListenAndServe(":80

我已经建立了TLS,它可以正常工作。我知道如何在nginx中从http重写为https,但我不再使用nginx了。我不知道该怎么做才能正常进行

func main() {

    certificate := "/srv/ssl/ssl-bundle.crt"
    privateKey := "/srv/ssl/mykey.key"

    http.HandleFunc("/", rootHander)
    // log.Fatal(http.ListenAndServe(":80", nil))
    log.Fatal(http.ListenAndServeTLS(":443", certificate, privateKey, nil))
}

func rootHander(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("To the moon!"))
}

如何以良好的方式执行此操作?

创建一个处理重定向到https的处理程序,如:

func redirectTLS(w http.ResponseWriter, r *http.Request) {
    http.Redirect(w, r, "https://IPAddr:443"+r.RequestURI, http.StatusMovedPermanently)
}
然后重定向http流量:

go func() {
    if err := http.ListenAndServe(":80", http.HandlerFunc(redirectTLS)); err != nil {
        log.Fatalf("ListenAndServe error: %v", err)
    }
}()

上面发布的解决方案有点不灵活,特别是当外部主机名与本地主机不同时

以下是我用于HTTP->HTTPS重定向的代码:

package main

import (
    "net"
    "log"
    "net/http"
)

var httpAddr ":8080"
var httpsAddr ":8443"

func main() {
    srv := http.Server{
        Addr: httpsAddr,
    }

    _, tlsPort, err := net.SplitHostPort(httpsAddr)
    if err != nil {
        return err
    }
    go redirectToHTTPS(tlsPort)

    srv.ListenAndServeTLS("cert.pem", "key.pem")
}

func redirectToHTTPS(tlsPort string) {
    httpSrv := http.Server{
        Addr: httpAddr,
        Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request){
            host, _, _ := net.SplitHostPort(r.Host)
            u := r.URL
            u.Host = net.JoinHostPort(host, tlsPort)
            u.Scheme="https"
            log.Println(u.String())
            http.Redirect(w,r,u.String(), http.StatusMovedPermanently)
        }),
    }
    log.Println(httpSrv.ListenAndServe())
}

如果您使用的是标准端口(80443),则不需要拆分地址连接,只需在URL上设置方案即可。

如果您使用自己的mux,这里还有另一个很好的示例和讨论:

非常感谢您!对于要重定向到的地址,最好使用
“https://”+r.Host+r.RequestURI
,这将避免主机名或IP地址被硬编码。
r.Host
从http请求中的
Host
头中获取。我认为它不应该被信任(见帖子),并且
r.RequestURI
可能包含像
http://localhost:5000
(见帖子)所以它太不可信了;博士,使用r.Host是实现这一点的正确方法,尽管用户可能会虚张声势有趣的讨论@MasBagol是非常正确的,用户可以“愚弄”或覆盖r.Host。但是,备选方案并不漂亮,这可能意味着要求管理员/用户配置“IPAddr”,这是一个坏主意。如果没有大量关于NAT/请求者环境的脆弱假设,就很难在不使用r.Host的情况下找出传递给http.Redirect()的内容。还有!举个例子,“黑客”只是设法让你的Go应用程序通过HTTP 301永久地移回他们自己的浏览器。谢谢你的帮助!我在几小时前的另一篇文章中给出了答案。祝您今天过得愉快!显式127.0.0.1地址有问题吗?它可能需要包含域名,例如“https://”+domain+r.RequestURI。此外,443是https的默认端口,可以省略。+10
net.JoinHostPort()
正是我所需要的。
package main

import (
    "net"
    "log"
    "net/http"
)

var httpAddr ":8080"
var httpsAddr ":8443"

func main() {
    srv := http.Server{
        Addr: httpsAddr,
    }

    _, tlsPort, err := net.SplitHostPort(httpsAddr)
    if err != nil {
        return err
    }
    go redirectToHTTPS(tlsPort)

    srv.ListenAndServeTLS("cert.pem", "key.pem")
}

func redirectToHTTPS(tlsPort string) {
    httpSrv := http.Server{
        Addr: httpAddr,
        Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request){
            host, _, _ := net.SplitHostPort(r.Host)
            u := r.URL
            u.Host = net.JoinHostPort(host, tlsPort)
            u.Scheme="https"
            log.Println(u.String())
            http.Redirect(w,r,u.String(), http.StatusMovedPermanently)
        }),
    }
    log.Println(httpSrv.ListenAndServe())
}