Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions httpbin/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,13 @@ func (h *HTTPBin) Headers(w http.ResponseWriter, r *http.Request) {
})
}

// ServerIP echoes the IP address of the server handling the request
func (h *HTTPBin) ServerIP(w http.ResponseWriter, _ *http.Request) {
writeJSON(http.StatusOK, w, &serverIPResponse{
ServerIP: getServerIP(),
})
}

type statusCase struct {
headers map[string]string
body []byte
Expand Down
32 changes: 32 additions & 0 deletions httpbin/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,38 @@ func getURL(r *http.Request) *url.URL {
}
}

// getServerIP attempts to determine the current server's primary IP address
// (e.g., Pod IP in Kubernetes). It prefers non-loopback IPv4 addresses, then
// falls back to non-loopback IPv6 if necessary.
func getServerIP() string {
// Prefer non-loopback IPv4 from interface addresses
if addrs, err := net.InterfaceAddrs(); err == nil {
var v6Fallback string
for _, a := range addrs {
if ipnet, ok := a.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
ip := ipnet.IP
if v4 := ip.To4(); v4 != nil {
return v4.String()
}
if v6Fallback == "" {
v6Fallback = ip.String()
}
}
}
if v6Fallback != "" {
return v6Fallback
}
}
// As a last resort, infer via a UDP dial (no packets actually sent)
if conn, err := net.Dial("udp", "8.8.8.8:80"); err == nil {
defer conn.Close()
if udp, ok := conn.LocalAddr().(*net.UDPAddr); ok && udp.IP != nil {
return udp.IP.String()
}
}
return ""
}

func writeResponse(w http.ResponseWriter, status int, contentType string, body []byte) {
w.Header().Set("Content-Type", contentType)
w.WriteHeader(status)
Expand Down
1 change: 1 addition & 0 deletions httpbin/httpbin.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ func (h *HTTPBin) Handler() http.Handler {
mux.HandleFunc("/image", h.ImageAccept)
mux.HandleFunc("/image/{kind}", h.Image)
mux.HandleFunc("/ip", h.IP)
mux.HandleFunc("/server-ip", h.ServerIP)
mux.HandleFunc("/json", h.JSON)
mux.HandleFunc("/links/{numLinks}", h.Links)
mux.HandleFunc("/links/{numLinks}/{offset}", h.Links)
Expand Down
4 changes: 4 additions & 0 deletions httpbin/responses.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ type hostnameResponse struct {
Hostname string `json:"hostname"`
}

type serverIPResponse struct {
ServerIP string `json:"server_ip"`
}

type errorRespnose struct {
StatusCode int `json:"status_code"`
Error string `json:"error"`
Expand Down