From 044c6239c86045018eb1e8e880ee50a8c5437f36 Mon Sep 17 00:00:00 2001 From: qf-dev1 Date: Sat, 11 Oct 2025 15:42:26 +0800 Subject: [PATCH] update --- go.mod | 38 +++++- go.sum | 90 ++++++++++++- main.go | 402 +++++--------------------------------------------------- 3 files changed, 156 insertions(+), 374 deletions(-) diff --git a/go.mod b/go.mod index 719013c..e19867d 100644 --- a/go.mod +++ b/go.mod @@ -1,5 +1,39 @@ module whoami -go 1.20 +go 1.24.1 -require github.com/gorilla/websocket v1.5.0 +require github.com/gin-gonic/gin v1.11.0 + +require ( + github.com/bytedance/sonic v1.14.0 // indirect + github.com/bytedance/sonic/loader v0.3.0 // indirect + github.com/cloudwego/base64x v0.1.6 // indirect + github.com/gabriel-vasile/mimetype v1.4.8 // indirect + github.com/gin-contrib/sse v1.1.0 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.27.0 // indirect + github.com/goccy/go-json v0.10.2 // indirect + github.com/goccy/go-yaml v1.18.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/cpuid/v2 v2.3.0 // indirect + github.com/leodido/go-urn v1.4.0 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/pelletier/go-toml/v2 v2.2.4 // indirect + github.com/quic-go/qpack v0.5.1 // indirect + github.com/quic-go/quic-go v0.54.0 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.3.0 // indirect + go.uber.org/mock v0.5.0 // indirect + golang.org/x/arch v0.20.0 // indirect + golang.org/x/crypto v0.40.0 // indirect + golang.org/x/mod v0.25.0 // indirect + golang.org/x/net v0.42.0 // indirect + golang.org/x/sync v0.16.0 // indirect + golang.org/x/sys v0.35.0 // indirect + golang.org/x/text v0.27.0 // indirect + golang.org/x/tools v0.34.0 // indirect + google.golang.org/protobuf v1.36.9 // indirect +) diff --git a/go.sum b/go.sum index e5a03d4..a25fff5 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +1,88 @@ -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/bytedance/sonic v1.14.0 h1:/OfKt8HFw0kh2rj8N0F6C/qPGRESq0BbaNZgcNXXzQQ= +github.com/bytedance/sonic v1.14.0/go.mod h1:WoEbx8WTcFJfzCe0hbmyTGrfjt8PzNEBdxlNUO24NhA= +github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA= +github.com/bytedance/sonic/loader v0.3.0/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI= +github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M= +github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM= +github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8= +github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w= +github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM= +github.com/gin-gonic/gin v1.11.0 h1:OW/6PLjyusp2PPXtyxKHU0RbX6I/l28FTdDlae5ueWk= +github.com/gin-gonic/gin v1.11.0/go.mod h1:+iq/FyxlGzII0KHiBGjuNn4UNENUlKbGlNmc+W50Dls= +github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.27.0 h1:w8+XrWVMhGkxOaaowyKH35gFydVHOvC0/uWoy2Fzwn4= +github.com/go-playground/validator/v10 v10.27.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw= +github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= +github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= +github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= +github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= +github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI= +github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg= +github.com/quic-go/quic-go v0.54.0 h1:6s1YB9QotYI6Ospeiguknbp2Znb/jZYjZLRXn9kMQBg= +github.com/quic-go/quic-go v0.54.0/go.mod h1:e68ZEaCdyviluZmy44P6Iey98v/Wfz6HCjQEm+l8zTY= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/ugorji/go/codec v1.3.0 h1:Qd2W2sQawAfG8XSvzwhBeoGq71zXOC/Q1E9y/wUcsUA= +github.com/ugorji/go/codec v1.3.0/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4= +go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU= +go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM= +golang.org/x/arch v0.20.0 h1:dx1zTU0MAE98U+TQ8BLl7XsJbgze2WnNKF/8tGp/Q6c= +golang.org/x/arch v0.20.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk= +golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM= +golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY= +golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w= +golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= +golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= +golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= +golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= +golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= +golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= +golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= +golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo= +golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg= +google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw= +google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go index 6969bd1..17d3a07 100644 --- a/main.go +++ b/main.go @@ -1,326 +1,46 @@ package main import ( - "crypto/tls" - "crypto/x509" - "encoding/json" - "errors" - "flag" "fmt" - "io" "log" "net" - "net/http" "os" - "strconv" "strings" - "sync" - "time" - "github.com/gorilla/websocket" + "github.com/gin-gonic/gin" ) -// Units. -const ( - _ = iota - KB int64 = 1 << (10 * iota) - MB - GB - TB -) - -var upgrader = websocket.Upgrader{ - ReadBufferSize: 1024, - WriteBufferSize: 1024, - CheckOrigin: func(r *http.Request) bool { - return true - }, -} - -var ( - cert string - key string - ca string - port string - name string - verbose bool -) - -func init() { - flag.BoolVar(&verbose, "verbose", false, "Enable verbose logging") - flag.StringVar(&cert, "cert", "", "give me a certificate") - flag.StringVar(&key, "key", "", "give me a key") - flag.StringVar(&ca, "cacert", "", "give me a CA chain, enforces mutual TLS") - flag.StringVar(&port, "port", getEnv("WHOAMI_PORT_NUMBER", "80"), "give me a port number") - flag.StringVar(&name, "name", os.Getenv("WHOAMI_NAME"), "give me a name") -} - -// Data whoami information. -type Data struct { - Hostname string `json:"hostname,omitempty"` - IP []string `json:"ip,omitempty"` - Headers http.Header `json:"headers,omitempty"` - URL string `json:"url,omitempty"` - Host string `json:"host,omitempty"` - Method string `json:"method,omitempty"` - Name string `json:"name,omitempty"` - RemoteAddr string `json:"remoteAddr,omitempty"` - Environ map[string]string `json:"environ,omitempty"` -} - func main() { - flag.Parse() - - mux := http.NewServeMux() - mux.Handle("/data", handle(dataHandler, verbose)) - mux.Handle("/echo", handle(echoHandler, verbose)) - mux.Handle("/bench", handle(benchHandler, verbose)) - mux.Handle("/api", handle(apiHandler, verbose)) - mux.Handle("/health", handle(healthHandler, verbose)) - mux.Handle("/", handle(whoamiHandler, verbose)) - - if cert == "" || key == "" { - log.Printf("Starting up on port %s", port) - - log.Fatal(http.ListenAndServe(":"+port, mux)) - } - - server := &http.Server{ - Addr: ":" + port, - Handler: mux, - } - - if len(ca) > 0 { - server.TLSConfig = setupMutualTLS(ca) - } - - log.Printf("Starting up with TLS on port %s", port) - - log.Fatal(server.ListenAndServeTLS(cert, key)) -} - -func setupMutualTLS(ca string) *tls.Config { - clientCACert, err := os.ReadFile(ca) - if err != nil { - log.Fatal(err) - } - - clientCertPool := x509.NewCertPool() - clientCertPool.AppendCertsFromPEM(clientCACert) - - tlsConfig := &tls.Config{ - ClientAuth: tls.RequireAndVerifyClientCert, - ClientCAs: clientCertPool, - PreferServerCipherSuites: true, - MinVersion: tls.VersionTLS12, - } - - return tlsConfig -} - -func handle(next http.HandlerFunc, verbose bool) http.Handler { - if !verbose { - return next - } - - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - next(w, r) - - // - [] " " - - log.Printf("%s - - [%s] \"%s %s %s\" - -", r.RemoteAddr, time.Now().Format("02/Jan/2006:15:04:05 -0700"), r.Method, r.URL.Path, r.Proto) + gin.SetMode(gin.ReleaseMode) + r := gin.Default() + r.Use(gin.Logger()) + r.Use(gin.Recovery()) + r.GET("/", func(c *gin.Context) { + log.Printf("user-agent=%s", c.Request.UserAgent()) + hostname, _ := os.Hostname() + resultText := fmt.Sprintf("Hostname: %s\nIP: %s\nRemoteAddr: %s\nUser-Agent: %s\nX-Forwarded-For: %s\nX-Forwarded-Port: %s\nX-Forwarded-Server: %s\nX-Real-IP: %s\n", + hostname, strings.Join(GetIps(), ", "), c.Request.RemoteAddr, c.Request.UserAgent(), c.Request.Header.Get("X-Forwarded-For"), + c.Request.Header.Get("X-Forwarded-Port"), c.Request.Header.Get("X-Forwarded-Server"), c.Request.Header.Get("X-Real-IP")) + c.String(200, resultText) }) -} - -func benchHandler(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Connection", "keep-alive") - w.Header().Set("Content-Type", "text/plain") - _, _ = fmt.Fprint(w, "1") -} - -func echoHandler(w http.ResponseWriter, r *http.Request) { - conn, err := upgrader.Upgrade(w, r, nil) - if err != nil { - log.Println(err) - return + port := ":80" + log.Printf("服务器启动在 http://localhost%s", port) + if err := r.Run(port); err != nil { + log.Fatal("服务器启动失败:", err) } +} - for { - messageType, p, err := conn.ReadMessage() +func GetIps() []string { + ips := []string{} + interfaces, _ := net.Interfaces() + for _, iface := range interfaces { + if iface.Flags&net.FlagUp == 0 { + continue + } + addrs, err := iface.Addrs() if err != nil { - return + continue } - - printBinary(p) - err = conn.WriteMessage(messageType, p) - if err != nil { - return - } - } -} - -func printBinary(s []byte) { - fmt.Printf("Received b:") - for n := 0; n < len(s); n++ { - fmt.Printf("%d,", s[n]) - } - fmt.Printf("\n") -} - -func dataHandler(w http.ResponseWriter, r *http.Request) { - queryParams := r.URL.Query() - - size, err := strconv.ParseInt(queryParams.Get("size"), 10, 64) - if err != nil { - size = 1 - } - if size < 0 { - size = 0 - } - - unit := queryParams.Get("unit") - switch strings.ToLower(unit) { - case "kb": - size *= KB - case "mb": - size *= MB - case "gb": - size *= GB - case "tb": - size *= TB - } - - attachment, err := strconv.ParseBool(queryParams.Get("attachment")) - if err != nil { - attachment = false - } - - content := &contentReader{size: size} - - if attachment { - w.Header().Set("Content-Disposition", "Attachment") - http.ServeContent(w, r, "data.txt", time.Now(), content) - return - } - - if _, err := io.Copy(w, content); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } -} - -func whoamiHandler(w http.ResponseWriter, r *http.Request) { - queryParams := r.URL.Query() - - wait := queryParams.Get("wait") - if len(wait) > 0 { - duration, err := time.ParseDuration(wait) - if err == nil { - time.Sleep(duration) - } - } - - if name != "" { - _, _ = fmt.Fprintln(w, "Name:", name) - } - - hostname, _ := os.Hostname() - _, _ = fmt.Fprintln(w, "Hostname:", hostname) - - for _, ip := range getIPs() { - _, _ = fmt.Fprintln(w, "IP:", ip) - } - - _, _ = fmt.Fprintln(w, "RemoteAddr:", r.RemoteAddr) - if err := r.Write(w); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - if ok, _ := strconv.ParseBool(queryParams.Get("env")); ok { - for _, env := range os.Environ() { - _, _ = fmt.Fprintln(w, env) - } - } -} - -func apiHandler(w http.ResponseWriter, r *http.Request) { - queryParams := r.URL.Query() - - hostname, _ := os.Hostname() - - environ := make(map[string]string) - - if ok, _ := strconv.ParseBool(queryParams.Get("env")); ok { - for _, env := range os.Environ() { - before, after, _ := strings.Cut(env, "=") - environ[before] = after - } - } - - data := Data{ - Hostname: hostname, - IP: getIPs(), - Headers: r.Header, - URL: r.URL.RequestURI(), - Host: r.Host, - Method: r.Method, - Name: name, - RemoteAddr: r.RemoteAddr, - Environ: environ, - } - - w.Header().Set("Content-Type", "application/json") - if err := json.NewEncoder(w).Encode(data); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } -} - -type healthState struct { - StatusCode int -} - -var ( - currentHealthState = healthState{http.StatusOK} - mutexHealthState = &sync.RWMutex{} -) - -func healthHandler(w http.ResponseWriter, req *http.Request) { - if req.Method == http.MethodPost { - var statusCode int - - if err := json.NewDecoder(req.Body).Decode(&statusCode); err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) - return - } - - fmt.Printf("Update health check status code [%d]\n", statusCode) - - mutexHealthState.Lock() - defer mutexHealthState.Unlock() - currentHealthState.StatusCode = statusCode - } else { - mutexHealthState.RLock() - defer mutexHealthState.RUnlock() - w.WriteHeader(currentHealthState.StatusCode) - } -} - -func getEnv(key, fallback string) string { - value := os.Getenv(key) - if value == "" { - return fallback - } - return value -} - -func getIPs() []string { - var ips []string - - ifaces, _ := net.Interfaces() - for _, i := range ifaces { - addrs, _ := i.Addrs() - // handle err for _, addr := range addrs { var ip net.IP switch v := addr.(type) { @@ -329,72 +49,14 @@ func getIPs() []string { case *net.IPAddr: ip = v.IP } - if ip != nil { - ips = append(ips, ip.String()) + if ip == nil || ip.IsLoopback() { + continue + } + ipStr := ip.String() + if ip.To4() != nil { + ips = append(ips, ipStr) } } } - return ips } - - -const contentCharset = "-ABCDEFGHIJKLMNOPQRSTUVWXYZ" - -type contentReader struct { - size int64 - cur int64 -} - -// Read implements the io.Read interface. -func (r *contentReader) Read(p []byte) (int, error) { - length := r.size - 1 - - if r.cur >= length { - return 0, io.EOF - } - if len(p) == 0 { - return 0, nil - } - - var n int - if r.cur == 0 { - p[n] = '|' - r.cur++ - n++ - } - - for n < len(p) && r.cur <= length { - p[n] = contentCharset[int(r.cur)%len(contentCharset)] - r.cur++ - n++ - } - - if r.cur >= length { - p[n-1] = '|' - } - - return n, nil -} - -// Seek implements the io.Seek interface. -func (r *contentReader) Seek(offset int64, whence int) (int64, error) { - switch whence { - default: - return 0, errors.New("seek: invalid whence") - case io.SeekStart: - offset += 0 - case io.SeekCurrent: - offset += r.cur - case io.SeekEnd: - offset += r.size - 1 - } - - if offset < 0 { - return 0, errors.New("seek: invalid offset") - } - - r.cur = offset - - return offset, nil -}