Listen on Unix socket

pull/89/head
Philipp Heckel 2022-01-10 16:28:13 -05:00
parent 014b561b29
commit 0b0595384e
3 changed files with 53 additions and 21 deletions

View File

@ -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: "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-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-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: "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: "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"}), 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") baseURL := c.String("base-url")
listenHTTP := c.String("listen-http") listenHTTP := c.String("listen-http")
listenHTTPS := c.String("listen-https") listenHTTPS := c.String("listen-https")
listenUnix := c.String("listen-unix")
keyFile := c.String("key-file") keyFile := c.String("key-file")
certFile := c.String("cert-file") certFile := c.String("cert-file")
firebaseKeyFile := c.String("firebase-key-file") firebaseKeyFile := c.String("firebase-key-file")
@ -112,6 +114,7 @@ func execServe(c *cli.Context) error {
conf.BaseURL = baseURL conf.BaseURL = baseURL
conf.ListenHTTP = listenHTTP conf.ListenHTTP = listenHTTP
conf.ListenHTTPS = listenHTTPS conf.ListenHTTPS = listenHTTPS
conf.ListenUnix = listenUnix
conf.KeyFile = keyFile conf.KeyFile = keyFile
conf.CertFile = certFile conf.CertFile = certFile
conf.FirebaseKeyFile = firebaseKeyFile conf.FirebaseKeyFile = firebaseKeyFile

View File

@ -36,6 +36,7 @@ type Config struct {
BaseURL string BaseURL string
ListenHTTP string ListenHTTP string
ListenHTTPS string ListenHTTPS string
ListenUnix string
KeyFile string KeyFile string
CertFile string CertFile string
FirebaseKeyFile string FirebaseKeyFile string

View File

@ -18,6 +18,7 @@ import (
"net" "net"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"os"
"regexp" "regexp"
"strconv" "strconv"
"strings" "strings"
@ -30,19 +31,20 @@ import (
// Server is the main server, providing the UI and API for ntfy // Server is the main server, providing the UI and API for ntfy
type Server struct { type Server struct {
config *Config config *Config
httpServer *http.Server httpServer *http.Server
httpsServer *http.Server httpsServer *http.Server
smtpServer *smtp.Server unixListener net.Listener
smtpBackend *smtpBackend smtpServer *smtp.Server
topics map[string]*topic smtpBackend *smtpBackend
visitors map[string]*visitor topics map[string]*topic
firebase subscriber visitors map[string]*visitor
mailer mailer firebase subscriber
messages int64 mailer mailer
cache cache messages int64
closeChan chan bool cache cache
mu sync.Mutex closeChan chan bool
mu sync.Mutex
} }
// errHTTP is a generic HTTP error for any non-200 HTTP error // 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 // Run executes the main server. It listens on HTTP (+ HTTPS, if configured), and starts
// a manager go routine to print stats and prune messages. // a manager go routine to print stats and prune messages.
func (s *Server) Run() error { 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 != "" { 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 != "" { 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 := http.NewServeMux()
mux.HandleFunc("/", s.handle) mux.HandleFunc("/", s.handle)
errChan := make(chan error) errChan := make(chan error)
s.mu.Lock() s.mu.Lock()
s.closeChan = make(chan bool) s.closeChan = make(chan bool)
s.httpServer = &http.Server{Addr: s.config.ListenHTTP, Handler: mux} if s.config.ListenHTTP != "" {
go func() { s.httpServer = &http.Server{Addr: s.config.ListenHTTP, Handler: mux}
errChan <- s.httpServer.ListenAndServe() go func() {
}() errChan <- s.httpServer.ListenAndServe()
}()
}
if s.config.ListenHTTPS != "" { if s.config.ListenHTTPS != "" {
s.httpsServer = &http.Server{Addr: s.config.ListenHTTP, Handler: mux} s.httpsServer = &http.Server{Addr: s.config.ListenHTTP, Handler: mux}
go func() { go func() {
errChan <- s.httpsServer.ListenAndServeTLS(s.config.CertFile, s.config.KeyFile) 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 != "" { if s.config.SMTPServerListen != "" {
go func() { go func() {
errChan <- s.runSMTPServer() errChan <- s.runSMTPServer()
@ -298,6 +323,9 @@ func (s *Server) Stop() {
if s.httpsServer != nil { if s.httpsServer != nil {
s.httpsServer.Close() s.httpsServer.Close()
} }
if s.unixListener != nil {
s.unixListener.Close()
}
if s.smtpServer != nil { if s.smtpServer != nil {
s.smtpServer.Close() s.smtpServer.Close()
} }