From c4c5c4923913c323a6bf9d811a2084e8ddefdbdb Mon Sep 17 00:00:00 2001 From: Guanran Wang Date: Sat, 2 Nov 2024 12:07:02 +0800 Subject: [PATCH] feat(api): allow listening with unix socket --- api/main.go | 61 +++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 52 insertions(+), 9 deletions(-) diff --git a/api/main.go b/api/main.go index 0aa8744..7a01a92 100644 --- a/api/main.go +++ b/api/main.go @@ -1,13 +1,17 @@ package main import ( + "context" "encoding/json" "errors" "fmt" + "io/fs" "log" "net" "net/http" "os" + "os/signal" + "strconv" "strings" "sync" @@ -27,10 +31,11 @@ const ( ) type serverConfig struct { - ASNDB string - CityDB string - Listen string - Mode string + ASNDB string + CityDB string + Listen string + Mode string + SocketPermission fs.FileMode } type body struct { @@ -47,11 +52,17 @@ type bodyError struct { } func main() { + perm, err := strconv.ParseUint(getEnvOr("IP_CHECKER_SOCKET_PERMISSION", "0600"), 8, 32) + if err != nil { + log.Fatal(err) + } + config = serverConfig{ - ASNDB: os.Getenv("IP_CHECKER_ASN_DB"), - CityDB: os.Getenv("IP_CHECKER_CITY_DB"), - Listen: getEnvOr("IP_CHECKER_LISTEN", ":8080"), - Mode: os.Getenv("IP_CHECKER_MODE"), + ASNDB: os.Getenv("IP_CHECKER_ASN_DB"), + CityDB: os.Getenv("IP_CHECKER_CITY_DB"), + Listen: getEnvOr("IP_CHECKER_LISTEN", ":8080"), + SocketPermission: fs.FileMode(perm), + Mode: os.Getenv("IP_CHECKER_MODE"), } if config.CityDB != "" { @@ -76,8 +87,40 @@ func main() { } http.HandleFunc("/api/v1/ip", handleRequest) + log.Printf("Starting server on %s", config.Listen) - log.Fatal(http.ListenAndServe(config.Listen, nil)) + + var srv http.Server + + // graceful shutdown + go func() { + sigint := make(chan os.Signal, 1) + signal.Notify(sigint, os.Interrupt) + <-sigint + + srv.Shutdown(context.Background()) + }() + + if strings.HasPrefix(config.Listen, "unix/") { + socketPath := strings.TrimPrefix(config.Listen, "unix/") + unixListener, err := net.Listen("unix", socketPath) + if err != nil { + log.Fatal(err) + } + + if err := os.Chmod(socketPath, config.SocketPermission); err != nil { + log.Fatal(err) + } + + if err := srv.Serve(unixListener); err != http.ErrServerClosed { + log.Fatal(err) + } + } else { + srv.Addr = config.Listen + if err := srv.ListenAndServe(); err != http.ErrServerClosed { + log.Fatal(err) + } + } } func generateJSON(ip string) (body, error) {