一尘不染

在同一程序中运行HTTP和HTTPS

go

为什么不能从同一个golang程序中同时运行HTTP和HTTPS?

这是启动两个服务器的代码。.首先启动的服务器将运行-第二个服务器将不运行。

运行程序时没有错误返回,但是请求http://www.localhosthttps://secure.localhost超时

//  Start HTTP
err_http := http.ListenAndServe(fmt.Sprintf(":%d", port), http_r)
if err_http != nil {
    log.Fatal("Web server (HTTP): ", err_http)
}

//  Start HTTPS
err_https := http.ListenAndServeTLS(fmt.Sprintf(":%d", ssl_port), "D:/Go/src/www/ssl/public.crt", "D:/Go/src/www/ssl/private.key", https_r)
if err_https != nil {
    log.Fatal("Web server (HTTPS): ", err_https)
}

这是完整的代码

package main

import (
    "net/http"
    "fmt"
    "log"
    "os"
    "io"
    "runtime"

    // go get github.com/gorilla/mux
    "github.com/gorilla/mux"
)

const (
    HOST = "localhost"
)

func Handler_404(w http.ResponseWriter, r *http.Request){
    fmt.Fprint(w, "Oops, something went wrong!")
}

func Handler_www(w http.ResponseWriter, r *http.Request){
    fmt.Fprint(w, "Hello world :)")
}

func Handler_api(w http.ResponseWriter, r *http.Request){
    fmt.Fprint(w, "This is the API")
}

func Handler_secure(w http.ResponseWriter, r *http.Request){
    fmt.Fprint(w, "This is Secure")
}

func redirect(r *mux.Router, from string, to string){
    r.Host(from).Subrouter().HandleFunc("/", func (w http.ResponseWriter, r *http.Request){
        http.Redirect(w, r, to, 301)
    })
}

func main(){
    port := 9000
    ssl_port := 443

    runtime.GOMAXPROCS(runtime.NumCPU())

    http_r := mux.NewRouter()
    https_r := mux.NewRouter()

    //  HTTP 404
    http_r.NotFoundHandler = http.HandlerFunc(Handler_404)

    //  Redirect "http://HOST" => "http://www.HOST"
    redirect(http_r, HOST, fmt.Sprintf("http://www.%s:%d", HOST, port))

    //  Redirect "http://secure.HOST" => "https://secure.HOST"
    redirect(http_r, "secure."+HOST, fmt.Sprintf("https://secure.%s", HOST))

    www := http_r.Host("www."+HOST).Subrouter()
    www.HandleFunc("/", Handler_www)

    api := http_r.Host("api."+HOST).Subrouter()
    api.HandleFunc("/", Handler_api)

    secure := https_r.Host("secure."+HOST).Subrouter()
    secure.HandleFunc("/", Handler_secure)

    //  Start HTTP
    err_http := http.ListenAndServe(fmt.Sprintf(":%d", port), http_r)
    if err_http != nil {
        log.Fatal("Web server (HTTP): ", err_http)
    }

    //  Start HTTPS
    err_https := http.ListenAndServeTLS(fmt.Sprintf(":%d", ssl_port), "D:/Go/src/www/ssl/public.crt", "D:/Go/src/www/ssl/private.key", https_r)
    if err_https != nil {
        log.Fatal("Web server (HTTPS): ", err_https)
    }
}

阅读 284

收藏
2020-07-02

共1个答案

一尘不染

ListenAndServeListenAndServeTLS打开侦听套接字,然后循环永远服务于客户端连接。这些函数仅在错误时返回。

主goroutine永远不会进入启动TLS服务器,因为主goroutine正忙于在ListenAndServe中等待HTTP连接。

要解决此问题,请在新的goroutine中启动HTTP服务器:

//  Start HTTP
go func() {
    err_http := http.ListenAndServe(fmt.Sprintf(":%d", port), http_r)
    if err_http != nil {
        log.Fatal("Web server (HTTP): ", err_http)
    }
 }()

//  Start HTTPS
err_https := http.ListenAndServeTLS(fmt.Sprintf(":%d", ssl_port),     "D:/Go/src/www/ssl/public.crt", "D:/Go/src/www/ssl/private.key", https_r)
if err_https != nil {
    log.Fatal("Web server (HTTPS): ", err_https)
}
2020-07-02