formidable/internal/server/server.go

107 lines
2.1 KiB
Go
Raw Normal View History

2022-03-22 09:21:55 +01:00
package server
import (
"context"
"fmt"
"log"
"net"
"net/http"
"forge.cadoles.com/wpetit/formidable/internal/server/template"
2022-05-10 22:31:17 +02:00
"github.com/go-chi/chi"
2022-03-22 09:21:55 +01:00
"github.com/pkg/errors"
"github.com/santhosh-tekuri/jsonschema/v5"
)
type Server struct {
host string
port uint
schema *jsonschema.Schema
defaults interface{}
values interface{}
2022-05-10 22:31:17 +02:00
onUpdate OnUpdateFunc
2022-03-22 09:21:55 +01:00
}
2022-05-10 22:31:17 +02:00
type OnUpdateFunc func(values interface{}) error
2022-03-22 09:21:55 +01:00
func (s *Server) Start(ctx context.Context) (<-chan net.Addr, <-chan error) {
errs := make(chan error)
addrs := make(chan net.Addr)
go s.run(ctx, addrs, errs)
return addrs, errs
}
func (s *Server) run(parentCtx context.Context, addrs chan net.Addr, errs chan error) {
ctx, cancel := context.WithCancel(parentCtx)
defer cancel()
listener, err := net.Listen("tcp", fmt.Sprintf("%s:%d", s.host, s.port))
if err != nil {
errs <- errors.WithStack(err)
return
}
addrs <- listener.Addr()
defer func() {
if err := listener.Close(); err != nil && !errors.Is(err, net.ErrClosed) {
errs <- errors.WithStack(err)
}
close(errs)
close(addrs)
}()
go func() {
<-ctx.Done()
if err := listener.Close(); err != nil && !errors.Is(err, net.ErrClosed) {
log.Printf("%+v", errors.WithStack(err))
}
}()
templates := getEmbeddedTemplates()
if err := template.Load(templates, "template"); err != nil {
2022-03-22 09:21:55 +01:00
errs <- errors.WithStack(err)
return
}
assets := getEmbeddedAssets()
assetsHandler := http.FileServer(http.FS(assets))
2022-05-10 22:31:17 +02:00
router := chi.NewRouter()
2022-03-22 09:21:55 +01:00
2022-05-10 22:31:17 +02:00
router.Get("/", s.serveFormReq)
router.Post("/", s.handleFormReq)
router.Handle("/assets/*", assetsHandler)
2022-03-22 09:21:55 +01:00
log.Println("http server listening")
2022-05-10 22:31:17 +02:00
if err := http.Serve(listener, router); err != nil && !errors.Is(err, net.ErrClosed) {
2022-03-22 09:21:55 +01:00
errs <- errors.WithStack(err)
}
log.Println("http server exiting")
}
func New(funcs ...OptionFunc) *Server {
opt := defaultOption()
for _, fn := range funcs {
fn(opt)
}
return &Server{
host: opt.Host,
port: opt.Port,
schema: opt.Schema,
defaults: opt.Defaults,
values: opt.Values,
2022-05-10 22:31:17 +02:00
onUpdate: opt.OnUpdate,
2022-03-22 09:21:55 +01:00
}
}