Improve web service related aspects

This commit is contained in:
2025-11-22 17:09:25 +08:00
parent 2a3ef3e52a
commit 27fc5c1fd6
7 changed files with 158 additions and 6 deletions

View File

@@ -0,0 +1 @@
package handler

20
internal/handler/stop.go Normal file
View File

@@ -0,0 +1,20 @@
package handler
import (
"log"
"os"
"os/signal"
"syscall"
)
// HandleStop handles the stop signal and exits the program.
func HandleStop() {
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
go func() {
sig := <-sigCh
log.Printf("[Info] Received signal: %vstopping...\r\n", sig)
os.Exit(0)
}()
}

View File

@@ -0,0 +1,55 @@
package service
import (
"encoding/json"
"os"
"path/filepath"
"sync"
)
var (
config Config
configOnce sync.Once
configErr error
configPath string
)
// loadConfig initializes the config from file
func loadConfig() {
exePath, err := os.Executable()
configPath := os.Getenv("CONFIG_PATH")
if err != nil {
configErr = err
return
}
if configPath == "" {
exeDir := filepath.Dir(exePath)
configPath = filepath.Join(exeDir, "config.json")
}
data, err := os.ReadFile(configPath)
if err != nil {
configErr = err
return
}
err = json.Unmarshal(data, &config)
if err != nil {
configErr = err
return
}
}
// GetConfig returns the singleton instance of the config.
// It's safe for concurrent use and loads the config only once per process lifetime.
func GetConfig() (*Config, error) {
configOnce.Do(loadConfig)
return &config, configErr
}
// ConfigPath returns the path to the loaded config file (useful for logging or reload later if needed)
func ConfigPath() string {
// Make sure config is at least attempted to be loaded
configOnce.Do(loadConfig)
return configPath
}

View File

@@ -0,0 +1 @@
package service

View File

@@ -5,8 +5,20 @@ type Config struct {
Server struct {
Host string `json:"host"`
Port int `json:"port"`
Tls struct {
Enabled bool `json:"enabled"`
Cert string `json:"cert_file"`
Key string `json:"key_file"`
} `json:"tls"`
Advanced struct {
Readtimeout int `json:"read_timeout"`
Writetimeout int `json:"write_timeout"`
Idletimeout int `json:"idle_timeout"`
Maxheaderbytes int `json:"max_header_bytes"`
} `json:"advanced"`
} `json:"server"`
Database struct {
Driver string `json:"driver"`
Host string `json:"host"`
Port int `json:"port"`
Username string `json:"username"`

View File

@@ -1,15 +1,66 @@
package service
import (
"crypto/tls"
"log"
"net/http"
"strconv"
"time"
)
func WebService() {
log.Printf("[Info] Starting web service")
log.Printf("[Info] Web service started on 0.0.0.0:2233")
err := http.ListenAndServe("0.0.0.0:2233", nil)
func getServerAddress(host string, port int) string {
return host + ":" + strconv.Itoa(port)
}
func CreateWebService() *http.Server {
log.Printf("[Info] Create web service")
config, err := GetConfig()
if err != nil {
log.Fatalf("[Error] Failed to start server: %v", err)
log.Fatalf("[Error] Failed to load config: %v", err)
}
addr := getServerAddress(config.Server.Host, config.Server.Port)
server := &http.Server{
Addr: addr,
ReadTimeout: time.Duration(config.Server.Advanced.Readtimeout) * time.Second,
WriteTimeout: time.Duration(config.Server.Advanced.Writetimeout) * time.Second,
IdleTimeout: time.Duration(config.Server.Advanced.Idletimeout) * time.Second,
MaxHeaderBytes: config.Server.Advanced.Maxheaderbytes << 16,
}
if config.Server.Tls.Enabled {
log.Printf("[Info] TLS enabled")
server.TLSConfig = &tls.Config{
PreferServerCipherSuites: true,
SessionTicketsDisabled: false,
}
}
return server
}
func ListenWebService(server *http.Server) {
config, err := GetConfig()
if err != nil {
log.Fatalf("[Error] Failed to load config: %v", err)
}
addr := getServerAddress(config.Server.Host, config.Server.Port)
if config.Server.Tls.Enabled {
log.Printf("[Info] Starting HTTPS server on %s", addr)
err := server.ListenAndServeTLS(
config.Server.Tls.Cert,
config.Server.Tls.Key,
)
if err != nil {
log.Fatalf("[Error] HTTPS server failed: %v", err)
}
} else {
log.Printf("[Info] Starting HTTP server on %s", addr)
err := server.ListenAndServe()
if err != nil {
log.Fatalf("[Error] HTTP server failed: %v", err)
}
}
if err != nil && err != http.ErrServerClosed {
log.Fatalf("[Error] Web server terminated unexpectedly: %v", err)
}
}