From 7e7ed646e2c3db2404b628e5e8b5584b9de0ff60 Mon Sep 17 00:00:00 2001 From: Shulhan Date: Mon, 2 Feb 2026 22:31:42 +0700 Subject: cmd/awwan: implement socket based activation on serve command The "awwan serve" command now can run based on socket activation under systemd. --- awwan.go | 5 +++-- cmd/awwan/main.go | 21 ++++++++++++++++++++- http_server.go | 8 +++++--- http_server_test.go | 10 +++++----- 4 files changed, 33 insertions(+), 11 deletions(-) diff --git a/awwan.go b/awwan.go index 06d59bf..82142aa 100644 --- a/awwan.go +++ b/awwan.go @@ -7,6 +7,7 @@ import ( "context" "fmt" "log" + "net" "os" "path/filepath" "strconv" @@ -483,14 +484,14 @@ out: } // Serve start the web-user interface that serve awwan through HTTP. -func (aww *Awwan) Serve(address string, isDev bool) (err error) { +func (aww *Awwan) Serve(listener net.Listener, address string, isDev bool) (err error) { var logp = `Serve` if isDev { go internal.Watch() } - aww.httpd, err = newHTTPServer(aww, address) + aww.httpd, err = newHTTPServer(aww, listener, address) if err != nil { return fmt.Errorf(`%s: %w`, logp, err) } diff --git a/cmd/awwan/main.go b/cmd/awwan/main.go index 39df4cb..5411515 100644 --- a/cmd/awwan/main.go +++ b/cmd/awwan/main.go @@ -10,10 +10,12 @@ import ( "flag" "fmt" "log" + "net" "os" "strings" "git.sr.ht/~shulhan/awwan" + "git.sr.ht/~shulhan/pakakeh.go/lib/systemd" ) const ( @@ -254,7 +256,24 @@ func main() { case awwan.CommandModePlay: err = aww.Play(ctx, req) case awwan.CommandModeServe: - err = aww.Serve(*serveAddress, *isDev) + var listeners []net.Listener + listeners, err = systemd.Listeners(true) + if err != nil { + log.Fatal(err) + } + if len(listeners) > 1 { + log.Fatal(`too many listeners received for activation`) + } + var listener net.Listener + if len(listeners) == 1 { + listener = listeners[0] + gotAddr := listener.Addr().String() + if gotAddr != *serveAddress { + log.Fatalf(`invalid Listener address, got %s, want %s`, + gotAddr, *serveAddress) + } + } + err = aww.Serve(listener, *serveAddress, *isDev) } if err != nil { log.Fatalf(`%s: %s`, logp, err) diff --git a/http_server.go b/http_server.go index df30db0..2a7f534 100644 --- a/http_server.go +++ b/http_server.go @@ -11,6 +11,7 @@ import ( "fmt" "io/fs" "log" + "net" "net/http" "os" "path" @@ -62,7 +63,7 @@ type httpServer struct { // newHTTPServer create and initialize HTTP server to serve awwan HTTP API // and web user interface. -func newHTTPServer(aww *Awwan, address string) (httpd *httpServer, err error) { +func newHTTPServer(aww *Awwan, listener net.Listener, address string) (httpd *httpServer, err error) { var ( logp = `newHTTPServer` ) @@ -92,8 +93,9 @@ func newHTTPServer(aww *Awwan, address string) (httpd *httpServer, err error) { } var serverOpts = libhttp.ServerOptions{ - Memfs: internal.MemfsWui, - Address: address, + Listener: listener, + Memfs: internal.MemfsWui, + Address: address, } httpd.Server, err = libhttp.NewServer(serverOpts) diff --git a/http_server_test.go b/http_server_test.go index 8617c65..f6a32aa 100644 --- a/http_server_test.go +++ b/http_server_test.go @@ -49,7 +49,7 @@ func TestHttpServer_Decrypt(t *testing.T) { var httpd *httpServer - httpd, err = newHTTPServer(aww, ``) + httpd, err = newHTTPServer(aww, nil, ``) if err != nil { t.Fatal(err) } @@ -133,7 +133,7 @@ func TestHttpServer_Encrypt(t *testing.T) { var httpd *httpServer - httpd, err = newHTTPServer(aww, ``) + httpd, err = newHTTPServer(aww, nil, ``) if err != nil { t.Fatal(err) } @@ -217,7 +217,7 @@ func TestHttpServer_Execute(t *testing.T) { ) go func() { - err = aww.Serve(address, isDev) + err = aww.Serve(nil, address, isDev) if err != nil { log.Fatal(err) } @@ -348,7 +348,7 @@ func TestHttpServer_ExecuteCancel(t *testing.T) { ) go func() { - err = aww.Serve(address, isDev) + err = aww.Serve(nil, address, isDev) if err != nil { log.Fatal(err) } @@ -497,7 +497,7 @@ func TestHttpServer_FSGet(t *testing.T) { var httpd *httpServer - httpd, err = newHTTPServer(aww, ``) + httpd, err = newHTTPServer(aww, nil, ``) if err != nil { t.Fatal(err) } -- cgit v1.3