107 lines
2.2 KiB
Go
107 lines
2.2 KiB
Go
package http
|
|
|
|
import (
|
|
"io/ioutil"
|
|
"net/http"
|
|
"strings"
|
|
"sync"
|
|
|
|
"forge.cadoles.com/arcad/edge/pkg/app"
|
|
"forge.cadoles.com/arcad/edge/pkg/bundle"
|
|
"forge.cadoles.com/arcad/edge/pkg/bus"
|
|
"forge.cadoles.com/arcad/edge/pkg/sdk"
|
|
"github.com/igm/sockjs-go/v3/sockjs"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
const (
|
|
sockJSPathPrefix = "/sock"
|
|
clientJSPath = "/client.js"
|
|
backendMainScript = "backend/main.js"
|
|
)
|
|
|
|
type Handler struct {
|
|
bundle bundle.Bundle
|
|
public http.Handler
|
|
|
|
sockjs http.Handler
|
|
bus bus.Bus
|
|
sockjsOpts sockjs.Options
|
|
|
|
backend *app.Backend
|
|
backendModuleFactories []app.BackendModuleFactory
|
|
|
|
mutex sync.RWMutex
|
|
}
|
|
|
|
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
h.mutex.RLock()
|
|
defer h.mutex.RUnlock()
|
|
|
|
switch {
|
|
case r.URL.Path == clientJSPath:
|
|
serveFile(w, r, &sdk.FS, "client/dist/client.js")
|
|
case r.URL.Path == clientJSPath+".map":
|
|
serveFile(w, r, &sdk.FS, "client/dist/client.js.map")
|
|
case strings.HasPrefix(r.URL.Path, sockJSPathPrefix):
|
|
h.sockjs.ServeHTTP(w, r)
|
|
default:
|
|
h.public.ServeHTTP(w, r)
|
|
}
|
|
}
|
|
|
|
func (h *Handler) Load(bdle bundle.Bundle) error {
|
|
h.mutex.Lock()
|
|
defer h.mutex.Unlock()
|
|
|
|
file, _, err := bdle.File(backendMainScript)
|
|
if err != nil {
|
|
return errors.Wrap(err, "could not open backend main script")
|
|
}
|
|
|
|
mainScript, err := ioutil.ReadAll(file)
|
|
if err != nil {
|
|
return errors.Wrap(err, "could not read backend main script")
|
|
}
|
|
|
|
backend := app.NewBackend(h.backendModuleFactories...)
|
|
|
|
if err := backend.Load(backendMainScript, string(mainScript)); err != nil {
|
|
return errors.WithStack(err)
|
|
}
|
|
|
|
fs := bundle.NewFileSystem("public", bdle)
|
|
public := http.FileServer(fs)
|
|
sockjs := sockjs.NewHandler(sockJSPathPrefix, h.sockjsOpts, h.handleSockJSSession)
|
|
|
|
if h.backend != nil {
|
|
h.backend.Stop()
|
|
}
|
|
|
|
if err := backend.Start(); err != nil {
|
|
return errors.WithStack(err)
|
|
}
|
|
|
|
h.bundle = bdle
|
|
h.backend = backend
|
|
h.public = public
|
|
h.sockjs = sockjs
|
|
|
|
return nil
|
|
}
|
|
|
|
func NewHandler(funcs ...HandlerOptionFunc) *Handler {
|
|
opts := defaultHandlerOptions()
|
|
for _, fn := range funcs {
|
|
fn(opts)
|
|
}
|
|
|
|
handler := &Handler{
|
|
sockjsOpts: opts.SockJS,
|
|
backendModuleFactories: opts.BackendModuleFactories,
|
|
bus: opts.Bus,
|
|
}
|
|
|
|
return handler
|
|
}
|