2020-12-04 15:28:02 +00:00
|
|
|
package server
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2021-11-12 12:08:56 +00:00
|
|
|
"io/fs"
|
2020-12-04 15:28:02 +00:00
|
|
|
"net"
|
|
|
|
"net/http"
|
|
|
|
|
2021-11-12 12:08:56 +00:00
|
|
|
"github.com/baez90/goveal/assets"
|
2020-12-06 11:18:42 +00:00
|
|
|
"github.com/baez90/goveal/internal/app/rendering"
|
|
|
|
"github.com/baez90/goveal/internal/app/routing"
|
2020-12-04 15:28:02 +00:00
|
|
|
)
|
|
|
|
|
2020-12-06 11:18:42 +00:00
|
|
|
const (
|
|
|
|
markdownFilePath = "/content.md"
|
|
|
|
)
|
|
|
|
|
2020-12-04 15:28:02 +00:00
|
|
|
type Config struct {
|
|
|
|
Host string
|
|
|
|
Port uint16
|
|
|
|
MarkdownPath string
|
|
|
|
RevealParams *rendering.RevealParams
|
|
|
|
}
|
|
|
|
|
|
|
|
type HTTPServer struct {
|
|
|
|
listener net.Listener
|
|
|
|
handler http.Handler
|
|
|
|
}
|
|
|
|
|
|
|
|
func (srv HTTPServer) Serve() error {
|
|
|
|
return http.Serve(srv.listener, srv.handler)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (srv HTTPServer) ListenAddress() string {
|
|
|
|
return srv.listener.Addr().String()
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewHTTPServer(config Config) (srv *HTTPServer, err error) {
|
2020-12-06 11:18:42 +00:00
|
|
|
noCacheFiles := append(config.RevealParams.FilesToMonitor, markdownFilePath)
|
|
|
|
|
2020-12-04 15:28:02 +00:00
|
|
|
router := &routing.RegexpRouter{}
|
|
|
|
var tmplRenderer rendering.RevealRenderer
|
|
|
|
if tmplRenderer, err = rendering.NewRevealRenderer(config.RevealParams); err != nil {
|
|
|
|
err = fmt.Errorf("failed to initialize reveal renderer %w", err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-11-12 12:08:56 +00:00
|
|
|
// language=regexp
|
|
|
|
if err = router.AddRule(`^(/(index.html(l)?)?)?$`, tmplRenderer); err != nil {
|
2020-12-04 15:28:02 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
var mdFS http.FileSystem
|
|
|
|
if mdFS, err = routing.NewMarkdownFS(config.MarkdownPath); err != nil {
|
|
|
|
err = fmt.Errorf("failed to initialize markdown file handler %w", err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-11-12 12:08:56 +00:00
|
|
|
var revealFS, webFS fs.FS
|
|
|
|
if revealFS, err = fs.Sub(assets.Assets, "reveal"); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if webFS, err = fs.Sub(assets.Assets, "web"); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
layeredFS := routing.NewLayeredFileSystem(http.FS(revealFS), http.FS(webFS), http.Dir("."), mdFS)
|
|
|
|
|
|
|
|
// language=regexp
|
|
|
|
if err = router.AddRule(`^(?i)/hash/(md5|sha1|sha2)/.*`, NewHashHandler(layeredFS)); err != nil {
|
2020-12-04 15:28:02 +00:00
|
|
|
return
|
|
|
|
}
|
2021-11-12 12:08:56 +00:00
|
|
|
// language=regexp
|
2020-12-06 11:18:42 +00:00
|
|
|
if err = router.AddRule("^/.*\\.md$", http.FileServer(mdFS)); err != nil {
|
2020-12-04 15:28:02 +00:00
|
|
|
return
|
|
|
|
}
|
2021-11-12 12:08:56 +00:00
|
|
|
// language=regexp
|
|
|
|
if err = router.AddRule("/.+", http.FileServer(layeredFS)); err != nil {
|
2020-12-04 15:28:02 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
hostPort := fmt.Sprintf("%s:%d", config.Host, config.Port)
|
|
|
|
|
|
|
|
srv = &HTTPServer{
|
2020-12-06 11:18:42 +00:00
|
|
|
handler: routing.NoCache(router, noCacheFiles),
|
2020-12-04 15:28:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if srv.listener, err = net.Listen("tcp", hostPort); err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|