1

I am try to start multiple http servers listening on different ports in same package. In my test HandleFunc function I need to print our host and the port of information of the http server which served the request. How would I do that?

Here is my sample code:

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)
}
Dinesh Gowda
  • 1,044
  • 3
  • 13
  • 29

2 Answers2

4

Use http.LocalAddrContextKey to retrieve the server address from the request context.

In my comment I suggested to use the ServerContextKey, but the http.Server.Addr field isn't always set, such as when using http.Server.Serve (and by extension http.Serve). The following example demonstrates that LocalAddrContextKey works with both http.ListenAndServe and 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
Peter
  • 29,454
  • 5
  • 48
  • 60
0

You can get it from request host by using r.Host . ref : https://golang.org/pkg/net/http/#Request