diff --git a/README.md b/README.md index 408c32e..d5d6365 100644 --- a/README.md +++ b/README.md @@ -192,7 +192,11 @@ cd MediaStationGo docker compose up -d ``` -> 🌐 服务启动后会自动识别本机 IP,日志中显示访问地址(如 `http://192.168.x.x:8080`),使用 `admin` / `admin123` 登录。 +> 🌐 服务启动后自动识别 **局域网 IP** 和 **公网 IP**(NAS / 服务器均可),日志示例: +> ```json +> {"msg":"server is ready","local":"http://192.168.1.4:8080","public":"http://1.2.3.4:8080"} +> ``` +> 使用 `admin` / `admin123` 登录。 ### 💻 裸机部署 diff --git a/README_EN.md b/README_EN.md index 2f36582..753d97f 100644 --- a/README_EN.md +++ b/README_EN.md @@ -192,7 +192,11 @@ cd MediaStationGo docker compose up -d ``` -> 🌐 The server auto-detects your local IP on startup and logs the access URL (e.g. `http://192.168.x.x:8080`). Log in with `admin` / `admin123`. +> 🌐 The server auto-detects both your **local network IP** and **public IP** on startup (NAS / VPS supported): +> ```json +> {"msg":"server is ready","local":"http://192.168.1.4:8080","public":"http://1.2.3.4:8080"} +> ``` +> Log in with `admin` / `admin123`. ### 💻 Bare Metal diff --git a/cmd/server/main.go b/cmd/server/main.go index 5efa001..f46a5f6 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -89,10 +89,19 @@ func main() { go func() { localIP := getLocalIP() - logger.Info("server is ready", - zap.String("local", fmt.Sprintf("http://%s:%d", localIP, cfg.App.Port)), - zap.String("listen", srv.Addr), - ) + publicIP := getPublicIP(3 * time.Second) + if publicIP != "" { + logger.Info("server is ready", + zap.String("local", fmt.Sprintf("http://%s:%d", localIP, cfg.App.Port)), + zap.String("public", fmt.Sprintf("http://%s:%d", publicIP, cfg.App.Port)), + zap.String("listen", srv.Addr), + ) + } else { + logger.Info("server is ready", + zap.String("local", fmt.Sprintf("http://%s:%d", localIP, cfg.App.Port)), + zap.String("listen", srv.Addr), + ) + } if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { logger.Fatal("listen failed", zap.Error(err)) } @@ -180,3 +189,20 @@ func getLocalIP() string { } return "localhost" } + +// getPublicIP tries to detect the public-facing IP by querying ipify.org. +// Returns empty string if detection fails (e.g. no internet, timeout). +func getPublicIP(timeout time.Duration) string { + client := &http.Client{Timeout: timeout} + resp, err := client.Get("https://api.ipify.org") + if err != nil { + return "" + } + defer resp.Body.Close() + buf := make([]byte, 64) + n, err := resp.Body.Read(buf) + if err != nil || n == 0 || resp.StatusCode != http.StatusOK { + return "" + } + return string(buf[:n]) +}