首页 > 解决方案 > HandleFunc 中的 http 主机和端口信息

问题描述

我正在尝试启动多个 http 服务器侦听同一包中的不同端口。在我的测试 HandleFunc 函数中,我需要打印我们的主机和服务请求的 http 服务器的信息端口。我该怎么做?

这是我的示例代码:

package main

import (
    "encoding/json"
    "flag"
    "log"
    "net/http"
    "os"

    "github.com/dineshgowda24/lb/backendserver/config"
)

func main() {
    c := flag.String("c", "config/config.json", "Please specify conf.json")
    flag.Parse()
    file, err := os.Open(*c)
    if err != nil {
        log.Fatal("Unable to open config file")
    }
    defer file.Close()
    decoder := json.NewDecoder(file)
    config := bconfig.BackendConfiguration{}
    err = decoder.Decode(&config)
    if err != nil {
        log.Fatal("Unable to decode conf.json file")
    }
    http.HandleFunc("/", handle)
    for _, s := range config.Servers {
        log.Printf("Started server at : %s : %s ", s.Host, s.Port)
        go func(host, port string) {
            if err := http.ListenAndServe(host+":"+port, nil); err != nil {
                log.Printf("Unable to start server at : %s : %s ", host, port)
            }
        }(s.Host, s.Port)
    }
    select {}
}

//How to get info of the server which served the request ??
func handle(w http.ResponseWriter, r *http.Request) {
    response := "I came from " //need to get server info
    w.Write([]byte(response))
    w.WriteHeader(http.StatusOK)
}

标签: gohttprequesthttpservergo-http

解决方案


使用http.LocalAddrContextKey从请求上下文中检索服务器地址。

在我的评论中,我建议使用 ServerContextKey,但并不总是设置 http.Server.Addr 字段,例如在使用http.Server.Serve(以及扩展为 http.Serve)时。以下示例演示了 LocalAddrContextKey 可与 http.ListenAndServe 和 http.Serve 一起使用:

package main

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

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        ctx := r.Context()

        srvAddr := ctx.Value(http.LocalAddrContextKey).(net.Addr)

        fmt.Println(srvAddr)
    })

    ln, err := net.Listen("tcp", "127.0.0.1:3000")
    if err != nil {
        log.Fatal(err)
    }

    go func() { log.Fatal(http.Serve(ln, nil)) }()
    go func() { log.Fatal(http.ListenAndServe("127.0.0.1:4000", nil)) }()

    resp, err := http.Get("http://localhost:3000")
    if err != nil {
        log.Fatal(err)
    }
    resp.Body.Close()

    resp, err = http.Get("http://localhost:4000")
    if err != nil {
        log.Fatal(err)
    }
    resp.Body.Close()

}

// Output:
// 127.0.0.1:3000
// 127.0.0.1:4000

推荐阅读