birthdaybot/server/web.go

86 lines
1.8 KiB
Go
Raw Normal View History

2023-07-11 11:37:56 +01:00
package server
import (
2023-07-11 12:27:50 +01:00
"encoding/json"
2023-07-11 11:37:56 +01:00
"errors"
"fmt"
"net"
2023-07-11 11:37:56 +01:00
"net/http"
"github.com/charmbracelet/log"
)
type WebServer struct {
server *Server
listener net.Listener
2023-07-11 11:37:56 +01:00
logger *log.Logger
httpServer *http.Server
}
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)
}
2023-07-11 11:37:56 +01:00
ws := &WebServer{
server: server,
listener: listener,
logger: server.Logger,
2023-07-11 11:37:56 +01:00
}
mux := http.NewServeMux()
mux.HandleFunc("/health", ws.healthHandler)
2023-07-11 12:27:50 +01:00
mux.HandleFunc("/next_birthdays", ws.nextBirthdayHandler)
2023-07-11 11:37:56 +01:00
ws.httpServer = &http.Server{Handler: mux}
2023-07-11 11:37:56 +01:00
return ws, nil
2023-07-11 11:37:56 +01:00
}
func (ws *WebServer) Start() error {
ws.logger.Debug("starting web server")
go func() {
if err := ws.httpServer.Serve(ws.listener); err != nil && !errors.Is(err, http.ErrServerClosed) {
2023-07-11 11:37:56 +01:00
ws.logger.Fatal("cannot start web server", "error", err)
}
}()
return nil
}
func (ws *WebServer) Stop() error {
ws.logger.Debug("stopping web server")
if err := ws.httpServer.Close(); err != nil {
return fmt.Errorf("cannot stop web server: %w", err)
}
return nil
}
func (ws *WebServer) Port() int {
return ws.listener.Addr().(*net.TCPAddr).Port
}
2023-07-11 11:37:56 +01:00
func (ws *WebServer) healthHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "OK")
}
2023-07-11 12:27:50 +01:00
func (ws *WebServer) nextBirthdayHandler(w http.ResponseWriter, r *http.Request) {
ws.JSON(w, http.StatusOK, ws.server.NextBirthdays())
}
func (ws *WebServer) JSON(w http.ResponseWriter, statusCode int, data any) {
b, err := json.Marshal(data)
if err != nil {
ws.logger.Error("cannot marshal data", "error", err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
w.WriteHeader(statusCode)
w.Write(b)
}