Как мне переписать / перенаправить с http на https в Go?

Я поднял TLS, и это работает. Я знаю, как переписать с http на https в nginx, но я больше не использую nginx. Я не знаю, как сделать это в Go правильно.

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!"))
}

Как бы я сделал это хорошим способом?

3 ответа

Решение

Создайте обработчик, который обрабатывает перенаправление на 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())
}

Если вы используете стандартные порты (80,443), разделение соединений адресов не требуется, и достаточно просто указать схему на URL.

Package main
import (
    "fmt"
    "net/http"
)
func redirectToHttps(w http.ResponseWriter, r *http.Request) {
    // Redirect the incoming HTTP request. Note that "127.0.0.1:443" will only work if you are accessing the server from your local machine.
    http.Redirect(w, r, "https://127.0.0.1:443"+r.RequestURI, http.StatusMovedPermanently)
}
func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hi there!")
    fmt.Println(r.RequestURI)
}
func main() {
    http.HandleFunc("/", handler)
    // Start the HTTPS server in a goroutine
    go http.ListenAndServeTLS(":443", "cert.pem", "key.pem", nil)
    // Start the HTTP server and redirect all incoming connections to HTTPS
    http.ListenAndServe(":8080", http.HandlerFunc(redirectToHttps))
}

Вот еще один отличный пример и обсуждение, если вы используете свой собственный мультиплексор:https://gist.github.com/d-schmidt/587ceec34ce1334a5e60

Другие вопросы по тегам