From 0b0595384e5dfe0157e81eb4ca4ed587cc20a652 Mon Sep 17 00:00:00 2001 From: Philipp Heckel Date: Mon, 10 Jan 2022 16:28:13 -0500 Subject: [PATCH] Listen on Unix socket --- cmd/serve.go | 3 +++ server/config.go | 1 + server/server.go | 70 +++++++++++++++++++++++++++++++++--------------- 3 files changed, 53 insertions(+), 21 deletions(-) diff --git a/cmd/serve.go b/cmd/serve.go index 5545206f..9e2a10cf 100644 --- a/cmd/serve.go +++ b/cmd/serve.go @@ -15,6 +15,7 @@ var flagsServe = []cli.Flag{ altsrc.NewStringFlag(&cli.StringFlag{Name: "base-url", Aliases: []string{"B"}, EnvVars: []string{"NTFY_BASE_URL"}, Usage: "externally visible base URL for this host (e.g. https://ntfy.sh)"}), altsrc.NewStringFlag(&cli.StringFlag{Name: "listen-http", Aliases: []string{"l"}, EnvVars: []string{"NTFY_LISTEN_HTTP"}, Value: server.DefaultListenHTTP, Usage: "ip:port used to as HTTP listen address"}), altsrc.NewStringFlag(&cli.StringFlag{Name: "listen-https", Aliases: []string{"L"}, EnvVars: []string{"NTFY_LISTEN_HTTPS"}, Usage: "ip:port used to as HTTPS listen address"}), + altsrc.NewStringFlag(&cli.StringFlag{Name: "listen-unix", Aliases: []string{"U"}, EnvVars: []string{"NTFY_LISTEN_UNIX"}, Usage: "listen on unix socket path"}), altsrc.NewStringFlag(&cli.StringFlag{Name: "key-file", Aliases: []string{"K"}, EnvVars: []string{"NTFY_KEY_FILE"}, Usage: "private key file, if listen-https is set"}), altsrc.NewStringFlag(&cli.StringFlag{Name: "cert-file", Aliases: []string{"E"}, EnvVars: []string{"NTFY_CERT_FILE"}, Usage: "certificate file, if listen-https is set"}), altsrc.NewStringFlag(&cli.StringFlag{Name: "firebase-key-file", Aliases: []string{"F"}, EnvVars: []string{"NTFY_FIREBASE_KEY_FILE"}, Usage: "Firebase credentials file; if set additionally publish to FCM topic"}), @@ -64,6 +65,7 @@ func execServe(c *cli.Context) error { baseURL := c.String("base-url") listenHTTP := c.String("listen-http") listenHTTPS := c.String("listen-https") + listenUnix := c.String("listen-unix") keyFile := c.String("key-file") certFile := c.String("cert-file") firebaseKeyFile := c.String("firebase-key-file") @@ -112,6 +114,7 @@ func execServe(c *cli.Context) error { conf.BaseURL = baseURL conf.ListenHTTP = listenHTTP conf.ListenHTTPS = listenHTTPS + conf.ListenUnix = listenUnix conf.KeyFile = keyFile conf.CertFile = certFile conf.FirebaseKeyFile = firebaseKeyFile diff --git a/server/config.go b/server/config.go index 30f937e9..56484a9b 100644 --- a/server/config.go +++ b/server/config.go @@ -36,6 +36,7 @@ type Config struct { BaseURL string ListenHTTP string ListenHTTPS string + ListenUnix string KeyFile string CertFile string FirebaseKeyFile string diff --git a/server/server.go b/server/server.go index 973fd367..7bd4add7 100644 --- a/server/server.go +++ b/server/server.go @@ -18,6 +18,7 @@ import ( "net" "net/http" "net/http/httptest" + "os" "regexp" "strconv" "strings" @@ -30,19 +31,20 @@ import ( // Server is the main server, providing the UI and API for ntfy type Server struct { - config *Config - httpServer *http.Server - httpsServer *http.Server - smtpServer *smtp.Server - smtpBackend *smtpBackend - topics map[string]*topic - visitors map[string]*visitor - firebase subscriber - mailer mailer - messages int64 - cache cache - closeChan chan bool - mu sync.Mutex + config *Config + httpServer *http.Server + httpsServer *http.Server + unixListener net.Listener + smtpServer *smtp.Server + smtpBackend *smtpBackend + topics map[string]*topic + visitors map[string]*visitor + firebase subscriber + mailer mailer + messages int64 + cache cache + closeChan chan bool + mu sync.Mutex } // errHTTP is a generic HTTP error for any non-200 HTTP error @@ -252,29 +254,52 @@ func maybeTruncateFCMMessage(m *messaging.Message) *messaging.Message { // Run executes the main server. It listens on HTTP (+ HTTPS, if configured), and starts // a manager go routine to print stats and prune messages. func (s *Server) Run() error { - listenStr := fmt.Sprintf("%s/http", s.config.ListenHTTP) + var listenStr string + if s.config.ListenHTTP != "" { + listenStr += fmt.Sprintf(" %s[http]", s.config.ListenHTTP) + } if s.config.ListenHTTPS != "" { - listenStr += fmt.Sprintf(" %s/https", s.config.ListenHTTPS) + listenStr += fmt.Sprintf(" %s[https]", s.config.ListenHTTPS) + } + if s.config.ListenUnix != "" { + listenStr += fmt.Sprintf(" %s[unix]", s.config.ListenUnix) } if s.config.SMTPServerListen != "" { - listenStr += fmt.Sprintf(" %s/smtp", s.config.SMTPServerListen) + listenStr += fmt.Sprintf(" %s[smtp]", s.config.SMTPServerListen) } - log.Printf("Listening on %s", listenStr) + log.Printf("Listening on%s", listenStr) mux := http.NewServeMux() mux.HandleFunc("/", s.handle) errChan := make(chan error) s.mu.Lock() s.closeChan = make(chan bool) - s.httpServer = &http.Server{Addr: s.config.ListenHTTP, Handler: mux} - go func() { - errChan <- s.httpServer.ListenAndServe() - }() + if s.config.ListenHTTP != "" { + s.httpServer = &http.Server{Addr: s.config.ListenHTTP, Handler: mux} + go func() { + errChan <- s.httpServer.ListenAndServe() + }() + } if s.config.ListenHTTPS != "" { s.httpsServer = &http.Server{Addr: s.config.ListenHTTP, Handler: mux} go func() { errChan <- s.httpsServer.ListenAndServeTLS(s.config.CertFile, s.config.KeyFile) }() } + if s.config.ListenUnix != "" { + go func() { + var err error + s.mu.Lock() + os.Remove(s.config.ListenUnix) + s.unixListener, err = net.Listen("unix", s.config.ListenUnix) + if err != nil { + errChan <- err + return + } + s.mu.Unlock() + httpServer := &http.Server{Handler: mux} + errChan <- httpServer.Serve(s.unixListener) + }() + } if s.config.SMTPServerListen != "" { go func() { errChan <- s.runSMTPServer() @@ -298,6 +323,9 @@ func (s *Server) Stop() { if s.httpsServer != nil { s.httpsServer.Close() } + if s.unixListener != nil { + s.unixListener.Close() + } if s.smtpServer != nil { s.smtpServer.Close() }