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 } }