100 lines
1.9 KiB
Go
100 lines
1.9 KiB
Go
package services
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"mailsrv/mail"
|
|
"mailsrv/runtime"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/rs/zerolog/log"
|
|
)
|
|
|
|
type HTTPServer interface {
|
|
Serve()
|
|
Done() <-chan struct{}
|
|
}
|
|
|
|
type Server struct {
|
|
ctx context.Context
|
|
fnCancel context.CancelFunc
|
|
|
|
port string
|
|
queue *runtime.Queue
|
|
|
|
chDone chan struct{}
|
|
}
|
|
|
|
func NewServer(ctx context.Context, port string, queue *runtime.Queue) Server {
|
|
ctxChild, fnCancel := context.WithCancel(ctx)
|
|
|
|
return Server{
|
|
ctx: ctxChild,
|
|
fnCancel: fnCancel,
|
|
port: port,
|
|
queue: queue,
|
|
chDone: make(chan struct{}),
|
|
}
|
|
}
|
|
|
|
func (s Server) Done() <-chan struct{} {
|
|
return s.chDone
|
|
}
|
|
|
|
func (s *Server) Serve() {
|
|
mux := http.NewServeMux()
|
|
mux.HandleFunc("/mail", s.handler)
|
|
|
|
log.Info().Str("port", s.port).Msg("http server is listening...")
|
|
|
|
server := &http.Server{
|
|
Addr: fmt.Sprintf(":%s", s.port),
|
|
Handler: mux,
|
|
ReadTimeout: 10 * time.Second,
|
|
WriteTimeout: 10 * time.Second,
|
|
}
|
|
|
|
go func() {
|
|
<-s.ctx.Done()
|
|
if err := server.Shutdown(s.ctx); err != nil {
|
|
log.Err(err).Msg("bad server shutdown")
|
|
}
|
|
s.chDone <- struct{}{}
|
|
}()
|
|
|
|
go func() {
|
|
if err := server.ListenAndServe(); err != nil {
|
|
log.Err(err).Msg("http server stops listening")
|
|
s.fnCancel()
|
|
}
|
|
}()
|
|
}
|
|
|
|
func (s *Server) handler(w http.ResponseWriter, r *http.Request) {
|
|
content, err := io.ReadAll(r.Body)
|
|
if err != nil {
|
|
log.Err(err).Msg("unable to read request body")
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
var email mail.Email
|
|
if err := json.Unmarshal(content, &email); err != nil {
|
|
log.Err(err).Msg("unable to deserialized request body into mail")
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
if err := email.Validate(); err != nil {
|
|
log.Err(err).Msg("email validation failed")
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
s.queue.Add(email)
|
|
w.WriteHeader(http.StatusOK)
|
|
}
|