Make web server optional and allow to use a random port
This commit is contained in:
parent
1cc687395c
commit
eaca9c1691
8 changed files with 56 additions and 25 deletions
|
@ -74,8 +74,8 @@ $ make run
|
||||||
- [X] Health endpoint
|
- [X] Health endpoint
|
||||||
- [X] Next birthdays endpoint
|
- [X] Next birthdays endpoint
|
||||||
- [ ] Birthday list endpoint
|
- [ ] Birthday list endpoint
|
||||||
- [ ] Allow to use a random port in web tests
|
- [X] Allow to use a random port in web tests
|
||||||
- [ ] Web server should be optional
|
- [X] Web server should be optional
|
||||||
- [ ] Create different message systems to use with the bot
|
- [ ] Create different message systems to use with the bot
|
||||||
- [X] Telegram
|
- [X] Telegram
|
||||||
- [ ] Email
|
- [ ] Email
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
---
|
---
|
||||||
web:
|
web:
|
||||||
|
enabled: true
|
||||||
port: 8080
|
port: 8080
|
||||||
|
|
||||||
birthdays:
|
birthdays:
|
||||||
|
|
|
@ -111,14 +111,11 @@ func (lc *LoggerConfig) IsValid() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
type WebConfig struct {
|
type WebConfig struct {
|
||||||
|
Enabled bool `yaml:"enabled"`
|
||||||
Port int `yaml:"port"`
|
Port int `yaml:"port"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (wc *WebConfig) SetDefaults() {
|
func (wc *WebConfig) SetDefaults() {}
|
||||||
if wc.Port == 0 {
|
|
||||||
wc.Port = 8080
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wc *WebConfig) IsValid() error {
|
func (wc *WebConfig) IsValid() error {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -28,9 +28,8 @@ func testConfig(t *testing.T) *model.Config {
|
||||||
require.NoError(t, f.Close())
|
require.NoError(t, f.Close())
|
||||||
require.NoError(t, os.Remove(f.Name()))
|
require.NoError(t, os.Remove(f.Name()))
|
||||||
|
|
||||||
// ToDo: allow for a random port to be used
|
|
||||||
return &model.Config{
|
return &model.Config{
|
||||||
Web: &model.WebConfig{Port: 9090},
|
Web: &model.WebConfig{Enabled: true, Port: 0},
|
||||||
Birthdays: &model.BirthdaysConfig{File: f.Name()},
|
Birthdays: &model.BirthdaysConfig{File: f.Name()},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,10 +108,15 @@ func New(options ...Option) (*Server, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if srv.WebServer == nil {
|
if srv.WebServer == nil && srv.Config.Web.Enabled {
|
||||||
srv.Logger.Debug("creating web server")
|
srv.Logger.Debug("creating web server")
|
||||||
|
|
||||||
srv.WebServer = NewWebServer(srv)
|
ws, err := NewWebServer(srv)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("cannot create web server: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
srv.WebServer = ws
|
||||||
}
|
}
|
||||||
|
|
||||||
return srv, nil
|
return srv, nil
|
||||||
|
@ -120,9 +125,11 @@ func New(options ...Option) (*Server, error) {
|
||||||
func (s *Server) Start() error {
|
func (s *Server) Start() error {
|
||||||
s.Logger.Info("starting server")
|
s.Logger.Info("starting server")
|
||||||
|
|
||||||
|
if s.WebServer != nil {
|
||||||
if err := s.WebServer.Start(); err != nil {
|
if err := s.WebServer.Start(); err != nil {
|
||||||
return fmt.Errorf("cannot start web server: %w", err)
|
return fmt.Errorf("cannot start web server: %w", err)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for _, worker := range s.workers {
|
for _, worker := range s.workers {
|
||||||
worker.Start()
|
worker.Start()
|
||||||
|
@ -136,9 +143,11 @@ func (s *Server) Start() error {
|
||||||
func (s *Server) Stop() error {
|
func (s *Server) Stop() error {
|
||||||
s.Logger.Info("stopping server")
|
s.Logger.Info("stopping server")
|
||||||
|
|
||||||
|
if s.WebServer != nil {
|
||||||
if err := s.WebServer.Stop(); err != nil {
|
if err := s.WebServer.Stop(); err != nil {
|
||||||
return fmt.Errorf("cannot stop web server: %w", err)
|
return fmt.Errorf("cannot stop web server: %w", err)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for _, worker := range s.workers {
|
for _, worker := range s.workers {
|
||||||
worker.Stop()
|
worker.Stop()
|
||||||
|
|
|
@ -15,6 +15,7 @@ import (
|
||||||
func TestNotify(t *testing.T) {
|
func TestNotify(t *testing.T) {
|
||||||
th := SetupTestHelper(t)
|
th := SetupTestHelper(t)
|
||||||
defer th.TearDown()
|
defer th.TearDown()
|
||||||
|
|
||||||
t.Run("should correctly use the notification services to notify", func(t *testing.T) {
|
t.Run("should correctly use the notification services to notify", func(t *testing.T) {
|
||||||
birthday := th.srv.birthdays[0]
|
birthday := th.srv.birthdays[0]
|
||||||
th.mockNotificationService.
|
th.mockNotificationService.
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/charmbracelet/log"
|
"github.com/charmbracelet/log"
|
||||||
|
@ -11,33 +12,37 @@ import (
|
||||||
|
|
||||||
type WebServer struct {
|
type WebServer struct {
|
||||||
server *Server
|
server *Server
|
||||||
|
listener net.Listener
|
||||||
logger *log.Logger
|
logger *log.Logger
|
||||||
httpServer *http.Server
|
httpServer *http.Server
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewWebServer(server *Server) *WebServer {
|
func NewWebServer(server *Server) (*WebServer, error) {
|
||||||
|
listener, err := net.Listen("tcp", fmt.Sprintf(":%d", server.Config.Web.Port))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("cannot create listener: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
ws := &WebServer{
|
ws := &WebServer{
|
||||||
server: server,
|
server: server,
|
||||||
|
listener: listener,
|
||||||
logger: server.Logger,
|
logger: server.Logger,
|
||||||
httpServer: &http.Server{
|
|
||||||
Addr: fmt.Sprintf(":%d", server.Config.Web.Port),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mux := http.NewServeMux()
|
mux := http.NewServeMux()
|
||||||
mux.HandleFunc("/health", ws.healthHandler)
|
mux.HandleFunc("/health", ws.healthHandler)
|
||||||
mux.HandleFunc("/next_birthdays", ws.nextBirthdayHandler)
|
mux.HandleFunc("/next_birthdays", ws.nextBirthdayHandler)
|
||||||
|
|
||||||
ws.httpServer.Handler = mux
|
ws.httpServer = &http.Server{Handler: mux}
|
||||||
|
|
||||||
return ws
|
return ws, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ws *WebServer) Start() error {
|
func (ws *WebServer) Start() error {
|
||||||
ws.logger.Debug("starting web server")
|
ws.logger.Debug("starting web server")
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
if err := ws.httpServer.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
if err := ws.httpServer.Serve(ws.listener); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||||
ws.logger.Fatal("cannot start web server", "error", err)
|
ws.logger.Fatal("cannot start web server", "error", err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
@ -55,6 +60,10 @@ func (ws *WebServer) Stop() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ws *WebServer) Port() int {
|
||||||
|
return ws.listener.Addr().(*net.TCPAddr).Port
|
||||||
|
}
|
||||||
|
|
||||||
func (ws *WebServer) healthHandler(w http.ResponseWriter, r *http.Request) {
|
func (ws *WebServer) healthHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
fmt.Fprint(w, "OK")
|
fmt.Fprint(w, "OK")
|
||||||
}
|
}
|
||||||
|
|
15
server/web_test.go
Normal file
15
server/web_test.go
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPort(t *testing.T) {
|
||||||
|
th := SetupTestHelper(t)
|
||||||
|
defer th.TearDown()
|
||||||
|
|
||||||
|
port := th.srv.WebServer.Port()
|
||||||
|
require.NotEmpty(t, port)
|
||||||
|
}
|
Loading…
Reference in a new issue