Skip to content

Instantly share code, notes, and snippets.

@yin1999
Last active Jun 30, 2022
Embed
What would you like to do?
package main
import (
"fmt"
"net"
"net/http"
"strings"
)
type mux struct {
}
func main() {
http.ListenAndServe(":9000", mux{})
}
const (
headerContentType = "Content-Type"
headerVersion = "Version"
)
func (mux) ServeHTTP(w http.ResponseWriter, req *http.Request) {
if req.URL.Path == "/favicon.ico" {
w.WriteHeader(http.StatusNotFound)
}
ip := req.Header.Get("X-Forwarded-For")
if ip != "" {
if index := strings.IndexByte(ip, ','); index != -1 {
ip = ip[:index]
}
} else {
ip, _, _ = net.SplitHostPort(req.RemoteAddr)
}
if ip != "" {
addr := net.ParseIP(ip)
if addr == nil {
w.WriteHeader(http.StatusBadRequest)
return
}
ipVersion := version(4)
if strings.IndexByte(ip, ':') != -1 {
ipVersion = 6
} else {
addr = addr.To4() // convert to 4 bytes IPv4
}
format := strings.ToLower(req.URL.Query().Get("format"))
switch format {
case "json":
w.Header().Add(headerContentType, "application/json")
fmt.Fprintf(w, "{\"version\":%s,\"address\":\"%s\"}", ipVersion.String(), addr.String())
case "", "plain":
w.Header().Add(headerContentType, "text/plain")
w.Header().Add(headerVersion, ipVersion.String())
w.Write([]byte(addr.String()))
case "binary":
w.Header().Add(headerContentType, "application/octet-stream")
w.Header().Add(headerVersion, ipVersion.String())
w.Write(addr)
default:
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("invalid format"))
}
}
}
type version byte
func (v version) String() string {
return string([]byte{'0' + byte(v)})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment