124 lines
2.6 KiB
Go
124 lines
2.6 KiB
Go
package fetch
|
|
|
|
import (
|
|
"context"
|
|
|
|
"forge.cadoles.com/arcad/edge/pkg/app"
|
|
"forge.cadoles.com/arcad/edge/pkg/bus"
|
|
"github.com/dop251/goja"
|
|
"github.com/pkg/errors"
|
|
"gitlab.com/wpetit/goweb/logger"
|
|
)
|
|
|
|
type Module struct {
|
|
server *app.Server
|
|
bus bus.Bus
|
|
}
|
|
|
|
func (m *Module) Name() string {
|
|
return "fetch"
|
|
}
|
|
|
|
func (m *Module) Export(export *goja.Object) {
|
|
funcs := map[string]any{
|
|
"get": m.get,
|
|
}
|
|
|
|
for name, fn := range funcs {
|
|
if err := export.Set(name, fn); err != nil {
|
|
panic(errors.Wrapf(err, "could not set '%s' function", name))
|
|
}
|
|
}
|
|
}
|
|
|
|
func (m *Module) get(call goja.FunctionCall, rt *goja.Runtime) goja.Value {
|
|
// ctx := util.AssertContext(call.Argument(0), rt)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (m *Module) handleMessages() {
|
|
ctx := context.Background()
|
|
|
|
fetchErrs := m.bus.Reply(ctx, AddressFetchRequest, func(env bus.Envelope) (any, error) {
|
|
fetchRequest, ok := env.Message().(*FetchRequest)
|
|
if !ok {
|
|
return nil, errors.Wrapf(bus.ErrUnexpectedMessage, "expected fetch request, got '%T'", env.Message())
|
|
}
|
|
|
|
res, err := m.handleFetchRequest(fetchRequest)
|
|
if err != nil {
|
|
logger.Error(ctx, "could not handle fetch request", logger.CapturedE(errors.WithStack(err)))
|
|
|
|
return nil, errors.WithStack(err)
|
|
}
|
|
|
|
logger.Debug(ctx, "fetch request response", logger.F("response", res))
|
|
|
|
return res, nil
|
|
})
|
|
|
|
for err := range fetchErrs {
|
|
logger.Fatal(ctx, "error while replying to fetch requests", logger.CapturedE(errors.WithStack(err)))
|
|
}
|
|
}
|
|
|
|
func (m *Module) handleFetchRequest(req *FetchRequest) (*FetchResponse, error) {
|
|
res := &FetchResponse{}
|
|
|
|
ctx := logger.With(
|
|
req.Context,
|
|
logger.F("url", req.URL.String()),
|
|
logger.F("remoteAddr", req.RemoteAddr),
|
|
logger.F("requestID", req.RequestID),
|
|
)
|
|
|
|
rawResult, err := m.server.ExecFuncByName(ctx, "onClientFetch", ctx, req.URL.String(), req.RemoteAddr)
|
|
if err != nil {
|
|
if errors.Is(err, app.ErrFuncDoesNotExist) {
|
|
res.Allow = false
|
|
|
|
return res, nil
|
|
}
|
|
|
|
return nil, errors.WithStack(err)
|
|
}
|
|
|
|
result, ok := rawResult.(map[string]interface{})
|
|
if !ok {
|
|
return nil, errors.Errorf(
|
|
"unexpected onClientFetch result: expected 'map[string]interface{}', got '%T'",
|
|
rawResult,
|
|
)
|
|
}
|
|
|
|
var allow bool
|
|
|
|
rawAllow, exists := result["allow"]
|
|
if !exists {
|
|
allow = false
|
|
} else {
|
|
allow, ok = rawAllow.(bool)
|
|
if !ok {
|
|
return nil, errors.Errorf("invalid 'allow' result property: got type '%T', expected type '%T'", rawAllow, false)
|
|
}
|
|
}
|
|
|
|
res.Allow = allow
|
|
|
|
return res, nil
|
|
}
|
|
|
|
func ModuleFactory(bus bus.Bus) app.ServerModuleFactory {
|
|
return func(server *app.Server) app.ServerModule {
|
|
mod := &Module{
|
|
bus: bus,
|
|
server: server,
|
|
}
|
|
|
|
go mod.handleMessages()
|
|
|
|
return mod
|
|
}
|
|
}
|