Skip to content

Commit f646d2a

Browse files
BoYanZhxhofe
andcommitted
feat!: listen to both http & https (AlistGo#4536)
Co-authored-by: Andy Hsu <[email protected]>
1 parent 363e036 commit f646d2a

File tree

6 files changed

+79
-29
lines changed

6 files changed

+79
-29
lines changed

Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,5 @@ COPY entrypoint.sh /entrypoint.sh
1414
RUN apk add --no-cache bash ca-certificates su-exec tzdata; \
1515
chmod +x /entrypoint.sh
1616
ENV PUID=0 PGID=0 UMASK=022
17-
EXPOSE 5244
17+
EXPOSE 5244 5245
1818
CMD [ "/entrypoint.sh" ]

cmd/server.go

+46-25
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"net/http"
77
"os"
88
"os/signal"
9+
"sync"
910
"syscall"
1011
"time"
1112

@@ -41,42 +42,62 @@ the address is defined in config file`,
4142
r := gin.New()
4243
r.Use(gin.LoggerWithWriter(log.StandardLogger().Out), gin.RecoveryWithWriter(log.StandardLogger().Out))
4344
server.Init(r)
44-
base := fmt.Sprintf("%s:%d", conf.Conf.Address, conf.Conf.Port)
45-
utils.Log.Infof("start server @ %s", base)
46-
srv := &http.Server{Addr: base, Handler: r}
47-
go func() {
48-
var err error
49-
if conf.Conf.Scheme.Https {
50-
//err = r.RunTLS(base, conf.Conf.Scheme.CertFile, conf.Conf.Scheme.KeyFile)
51-
err = srv.ListenAndServeTLS(conf.Conf.Scheme.CertFile, conf.Conf.Scheme.KeyFile)
52-
} else {
53-
err = srv.ListenAndServe()
54-
}
55-
if err != nil && err != http.ErrServerClosed {
56-
utils.Log.Fatalf("failed to start: %s", err.Error())
57-
}
58-
}()
45+
var httpSrv, httpsSrv *http.Server
46+
if !conf.Conf.Scheme.DisableHttp {
47+
httpBase := fmt.Sprintf("%s:%d", conf.Conf.Address, conf.Conf.Port)
48+
utils.Log.Infof("start HTTP server @ %s", httpBase)
49+
httpSrv = &http.Server{Addr: httpBase, Handler: r}
50+
go func() {
51+
err := httpSrv.ListenAndServe()
52+
if err != nil && err != http.ErrServerClosed {
53+
utils.Log.Fatalf("failed to start: %s", err.Error())
54+
}
55+
}()
56+
}
57+
if conf.Conf.Scheme.Https {
58+
httpsBase := fmt.Sprintf("%s:%d", conf.Conf.Address, conf.Conf.HttpsPort)
59+
utils.Log.Infof("start HTTPS server @ %s", httpsBase)
60+
httpsSrv = &http.Server{Addr: httpsBase, Handler: r}
61+
go func() {
62+
err := httpsSrv.ListenAndServeTLS(conf.Conf.Scheme.CertFile, conf.Conf.Scheme.KeyFile)
63+
if err != nil && err != http.ErrServerClosed {
64+
utils.Log.Fatalf("failed to start: %s", err.Error())
65+
}
66+
}()
67+
}
5968
// Wait for interrupt signal to gracefully shutdown the server with
60-
// a timeout of 5 seconds.
61-
quit := make(chan os.Signal)
69+
// a timeout of 1 second.
70+
quit := make(chan os.Signal, 1)
6271
// kill (no param) default send syscanll.SIGTERM
6372
// kill -2 is syscall.SIGINT
6473
// kill -9 is syscall. SIGKILL but can"t be catch, so don't need add it
6574
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
6675
<-quit
67-
utils.Log.Println("Shutdown Server ...")
76+
utils.Log.Println("Shutdown server...")
6877

6978
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
7079
defer cancel()
71-
if err := srv.Shutdown(ctx); err != nil {
72-
utils.Log.Fatal("Server Shutdown:", err)
80+
var wg sync.WaitGroup
81+
if !conf.Conf.Scheme.DisableHttp {
82+
wg.Add(1)
83+
go func() {
84+
defer wg.Done()
85+
if err := httpSrv.Shutdown(ctx); err != nil {
86+
utils.Log.Fatal("HTTP server shutdown:", err)
87+
}
88+
}()
7389
}
74-
// catching ctx.Done(). timeout of 3 seconds.
75-
select {
76-
case <-ctx.Done():
77-
utils.Log.Println("timeout of 1 seconds.")
90+
if conf.Conf.Scheme.Https {
91+
wg.Add(1)
92+
go func() {
93+
defer wg.Done()
94+
if err := httpsSrv.Shutdown(ctx); err != nil {
95+
utils.Log.Fatal("HTTPS server shutdown:", err)
96+
}
97+
}()
7898
}
79-
utils.Log.Println("Server exiting")
99+
wg.Wait()
100+
utils.Log.Println("Server exit")
80101
},
81102
}
82103

docker-compose.yml

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ services:
66
- '/etc/alist:/opt/alist/data'
77
ports:
88
- '5244:5244'
9+
- '5245:5245'
910
environment:
1011
- PUID=0
1112
- PGID=0

internal/conf/config.go

+7-3
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@ type Database struct {
2020
}
2121

2222
type Scheme struct {
23-
Https bool `json:"https" env:"HTTPS"`
24-
CertFile string `json:"cert_file" env:"CERT_FILE"`
25-
KeyFile string `json:"key_file" env:"KEY_FILE"`
23+
DisableHttp bool `json:"disable_http" env:"DISABLE_HTTP"`
24+
Https bool `json:"https" env:"HTTPS"`
25+
ForceHttps bool `json:"force_https" env:"FORCE_HTTPS"`
26+
CertFile string `json:"cert_file" env:"CERT_FILE"`
27+
KeyFile string `json:"key_file" env:"KEY_FILE"`
2628
}
2729

2830
type LogConfig struct {
@@ -38,6 +40,7 @@ type Config struct {
3840
Force bool `json:"force" env:"FORCE"`
3941
Address string `json:"address" env:"ADDR"`
4042
Port int `json:"port" env:"PORT"`
43+
HttpsPort int `json:"https_port" env:"HTTPS_PORT"`
4144
SiteURL string `json:"site_url" env:"SITE_URL"`
4245
Cdn string `json:"cdn" env:"CDN"`
4346
JwtSecret string `json:"jwt_secret" env:"JWT_SECRET"`
@@ -60,6 +63,7 @@ func DefaultConfig() *Config {
6063
return &Config{
6164
Address: "0.0.0.0",
6265
Port: 5244,
66+
HttpsPort: 5245,
6367
JwtSecret: random.String(16),
6468
TokenExpiresIn: 48,
6569
TempDir: tempDir,

server/middlewares/https.go

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package middlewares
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
7+
"github.com/alist-org/alist/v3/internal/conf"
8+
"github.com/gin-gonic/gin"
9+
)
10+
11+
func ForceHttps(c *gin.Context) {
12+
if c.Request.TLS == nil {
13+
host := c.Request.Host
14+
// change port to https port
15+
host = strings.Replace(host, fmt.Sprintf(":%d", conf.Conf.Port), fmt.Sprintf(":%d", conf.Conf.HttpsPort), 1)
16+
c.Redirect(302, "https://"+host+c.Request.RequestURI)
17+
c.Abort()
18+
return
19+
}
20+
c.Next()
21+
}

server/router.go

+3
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ func Init(e *gin.Engine) {
2121
}
2222
Cors(e)
2323
g := e.Group(conf.URL.Path)
24+
if conf.Conf.Scheme.Https && conf.Conf.Scheme.ForceHttps && !conf.Conf.Scheme.DisableHttp {
25+
g.Use(middlewares.ForceHttps)
26+
}
2427
g.Any("/ping", func(c *gin.Context) {
2528
c.String(200, "pong")
2629
})

0 commit comments

Comments
 (0)