feat!: support listen to the unix (close #4671)

Starting from this commit, the HTTP server related config all move to the scheme
pull/4522/head
Andy Hsu 2023-07-04 17:56:02 +08:00
parent 59dbf4496f
commit 7d20a01dba
4 changed files with 53 additions and 24 deletions

View File

@ -3,6 +3,7 @@ package cmd
import ( import (
"context" "context"
"fmt" "fmt"
"net"
"net/http" "net/http"
"os" "os"
"os/signal" "os/signal"
@ -42,26 +43,40 @@ the address is defined in config file`,
r := gin.New() r := gin.New()
r.Use(gin.LoggerWithWriter(log.StandardLogger().Out), gin.RecoveryWithWriter(log.StandardLogger().Out)) r.Use(gin.LoggerWithWriter(log.StandardLogger().Out), gin.RecoveryWithWriter(log.StandardLogger().Out))
server.Init(r) server.Init(r)
var httpSrv, httpsSrv *http.Server var httpSrv, httpsSrv, unixSrv *http.Server
if !conf.Conf.Scheme.DisableHttp { if conf.Conf.Scheme.HttpPort != -1 {
httpBase := fmt.Sprintf("%s:%d", conf.Conf.Address, conf.Conf.Port) httpBase := fmt.Sprintf("%s:%d", conf.Conf.Scheme.Address, conf.Conf.Scheme.HttpPort)
utils.Log.Infof("start HTTP server @ %s", httpBase) utils.Log.Infof("start HTTP server @ %s", httpBase)
httpSrv = &http.Server{Addr: httpBase, Handler: r} httpSrv = &http.Server{Addr: httpBase, Handler: r}
go func() { go func() {
err := httpSrv.ListenAndServe() err := httpSrv.ListenAndServe()
if err != nil && err != http.ErrServerClosed { if err != nil && err != http.ErrServerClosed {
utils.Log.Fatalf("failed to start: %s", err.Error()) utils.Log.Fatalf("failed to start http: %s", err.Error())
} }
}() }()
} }
if conf.Conf.Scheme.Https { if conf.Conf.Scheme.HttpsPort != -1 {
httpsBase := fmt.Sprintf("%s:%d", conf.Conf.Address, conf.Conf.HttpsPort) httpsBase := fmt.Sprintf("%s:%d", conf.Conf.Scheme.Address, conf.Conf.Scheme.HttpPort)
utils.Log.Infof("start HTTPS server @ %s", httpsBase) utils.Log.Infof("start HTTPS server @ %s", httpsBase)
httpsSrv = &http.Server{Addr: httpsBase, Handler: r} httpsSrv = &http.Server{Addr: httpsBase, Handler: r}
go func() { go func() {
err := httpsSrv.ListenAndServeTLS(conf.Conf.Scheme.CertFile, conf.Conf.Scheme.KeyFile) err := httpsSrv.ListenAndServeTLS(conf.Conf.Scheme.CertFile, conf.Conf.Scheme.KeyFile)
if err != nil && err != http.ErrServerClosed { if err != nil && err != http.ErrServerClosed {
utils.Log.Fatalf("failed to start: %s", err.Error()) utils.Log.Fatalf("failed to start https: %s", err.Error())
}
}()
}
if conf.Conf.Scheme.UnixFile != "" {
utils.Log.Infof("start unix server @ %s", conf.Conf.Scheme.UnixFile)
unixSrv = &http.Server{Handler: r}
go func() {
listener, err := net.Listen("unix", conf.Conf.Scheme.UnixFile)
if err != nil {
utils.Log.Fatalf("failed to listen unix: %+v", err)
}
err = unixSrv.Serve(listener)
if err != nil && err != http.ErrServerClosed {
utils.Log.Fatalf("failed to start unix: %s", err.Error())
} }
}() }()
} }
@ -78,21 +93,30 @@ the address is defined in config file`,
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel() defer cancel()
var wg sync.WaitGroup var wg sync.WaitGroup
if !conf.Conf.Scheme.DisableHttp { if conf.Conf.Scheme.HttpPort != -1 {
wg.Add(1) wg.Add(1)
go func() { go func() {
defer wg.Done() defer wg.Done()
if err := httpSrv.Shutdown(ctx); err != nil { if err := httpSrv.Shutdown(ctx); err != nil {
utils.Log.Fatal("HTTP server shutdown:", err) utils.Log.Fatal("HTTP server shutdown err: ", err)
} }
}() }()
} }
if conf.Conf.Scheme.Https { if conf.Conf.Scheme.HttpsPort != -1 {
wg.Add(1) wg.Add(1)
go func() { go func() {
defer wg.Done() defer wg.Done()
if err := httpsSrv.Shutdown(ctx); err != nil { if err := httpsSrv.Shutdown(ctx); err != nil {
utils.Log.Fatal("HTTPS server shutdown:", err) utils.Log.Fatal("HTTPS server shutdown err: ", err)
}
}()
}
if conf.Conf.Scheme.UnixFile != "" {
wg.Add(1)
go func() {
defer wg.Done()
if err := unixSrv.Shutdown(ctx); err != nil {
utils.Log.Fatal("Unix server shutdown err: ", err)
} }
}() }()
} }

View File

@ -20,11 +20,13 @@ type Database struct {
} }
type Scheme struct { type Scheme struct {
DisableHttp bool `json:"disable_http" env:"DISABLE_HTTP"` Address string `json:"address" env:"ADDR"`
Https bool `json:"https" env:"HTTPS"` HttpPort int `json:"http_port" env:"HTTP_PORT"`
ForceHttps bool `json:"force_https" env:"FORCE_HTTPS"` HttpsPort int `json:"https_port" env:"HTTPS_PORT"`
CertFile string `json:"cert_file" env:"CERT_FILE"` ForceHttps bool `json:"force_https" env:"FORCE_HTTPS"`
KeyFile string `json:"key_file" env:"KEY_FILE"` CertFile string `json:"cert_file" env:"CERT_FILE"`
KeyFile string `json:"key_file" env:"KEY_FILE"`
UnixFile string `json:"unix_file" env:"UNIX_FILE"`
} }
type LogConfig struct { type LogConfig struct {
@ -38,9 +40,6 @@ type LogConfig struct {
type Config struct { type Config struct {
Force bool `json:"force" env:"FORCE"` Force bool `json:"force" env:"FORCE"`
Address string `json:"address" env:"ADDR"`
Port int `json:"port" env:"PORT"`
HttpsPort int `json:"https_port" env:"HTTPS_PORT"`
SiteURL string `json:"site_url" env:"SITE_URL"` SiteURL string `json:"site_url" env:"SITE_URL"`
Cdn string `json:"cdn" env:"CDN"` Cdn string `json:"cdn" env:"CDN"`
JwtSecret string `json:"jwt_secret" env:"JWT_SECRET"` JwtSecret string `json:"jwt_secret" env:"JWT_SECRET"`
@ -61,9 +60,15 @@ func DefaultConfig() *Config {
logPath := filepath.Join(flags.DataDir, "log/log.log") logPath := filepath.Join(flags.DataDir, "log/log.log")
dbPath := filepath.Join(flags.DataDir, "data.db") dbPath := filepath.Join(flags.DataDir, "data.db")
return &Config{ return &Config{
Address: "0.0.0.0", Scheme: Scheme{
Port: 5244, Address: "0.0.0.0",
HttpsPort: 5245, UnixFile: "",
HttpPort: 5244,
HttpsPort: -1,
ForceHttps: false,
CertFile: "",
KeyFile: "",
},
JwtSecret: random.String(16), JwtSecret: random.String(16),
TokenExpiresIn: 48, TokenExpiresIn: 48,
TempDir: tempDir, TempDir: tempDir,

View File

@ -12,7 +12,7 @@ func ForceHttps(c *gin.Context) {
if c.Request.TLS == nil { if c.Request.TLS == nil {
host := c.Request.Host host := c.Request.Host
// change port to https port // change port to https port
host = strings.Replace(host, fmt.Sprintf(":%d", conf.Conf.Port), fmt.Sprintf(":%d", conf.Conf.HttpsPort), 1) host = strings.Replace(host, fmt.Sprintf(":%d", conf.Conf.Scheme.HttpPort), fmt.Sprintf(":%d", conf.Conf.Scheme.HttpsPort), 1)
c.Redirect(302, "https://"+host+c.Request.RequestURI) c.Redirect(302, "https://"+host+c.Request.RequestURI)
c.Abort() c.Abort()
return return

View File

@ -21,7 +21,7 @@ func Init(e *gin.Engine) {
} }
Cors(e) Cors(e)
g := e.Group(conf.URL.Path) g := e.Group(conf.URL.Path)
if conf.Conf.Scheme.Https && conf.Conf.Scheme.ForceHttps && !conf.Conf.Scheme.DisableHttp { if conf.Conf.Scheme.HttpPort != -1 && conf.Conf.Scheme.HttpsPort != -1 && conf.Conf.Scheme.ForceHttps {
g.Use(middlewares.ForceHttps) g.Use(middlewares.ForceHttps)
} }
g.Any("/ping", func(c *gin.Context) { g.Any("/ping", func(c *gin.Context) {