diff --git a/backend/controller/controller.go b/backend/controller/controller.go index 99e017f3f1..96a445e803 100644 --- a/backend/controller/controller.go +++ b/backend/controller/controller.go @@ -184,16 +184,11 @@ func (s *Service) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } - deployments, err := s.dal.GetActiveDeployments(r.Context()) + sch, err := s.getActiveSchema(r.Context()) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } - sch := &schema.Schema{ - Modules: slices.Map(deployments, func(d dal.Deployment) *schema.Module { - return d.Schema - }), - } body, err := ingress.ValidateAndExtractBody(route, r, sch) if err != nil { @@ -587,6 +582,16 @@ func (s *Service) Call(ctx context.Context, req *connect.Request[ftlv1.CallReque } verbRef := schema.VerbRefFromProto(req.Msg.Verb) + sch, err := s.getActiveSchema(ctx) + if err != nil { + return nil, err + } + + err = ingress.ValidateCallBody(req.Msg.Body, verbRef, sch) + if err != nil { + return nil, err + } + module := verbRef.Module s.routesMu.RLock() routes, ok := s.routes[module] @@ -1042,6 +1047,18 @@ func (s *Service) syncRoutes(ctx context.Context) error { return nil } +func (s *Service) getActiveSchema(ctx context.Context) (*schema.Schema, error) { + deployments, err := s.dal.GetActiveDeployments(ctx) + if err != nil { + return nil, err + } + return &schema.Schema{ + Modules: slices.Map(deployments, func(d dal.Deployment) *schema.Module { + return d.Schema + }), + }, nil +} + // Copied from the Apache-licensed connect-go source. func connectCodeToHTTP(code connect.Code) int { switch code { diff --git a/backend/controller/ingress/ingress.go b/backend/controller/ingress/ingress.go index ac46d4bcd2..abb2fbbc18 100644 --- a/backend/controller/ingress/ingress.go +++ b/backend/controller/ingress/ingress.go @@ -58,6 +58,25 @@ func matchSegments(pattern, urlPath string, onMatch func(segment, value string)) return true } +func ValidateCallBody(body []byte, verbRef *schema.VerbRef, sch *schema.Schema) error { + var requestMap map[string]any + err := json.Unmarshal(body, &requestMap) + if err != nil { + return fmt.Errorf("HTTP request body is not valid JSON: %w", err) + } + + verb := sch.ResolveVerbRef(verbRef) + if verb == nil { + return fmt.Errorf("unknown verb %s", verbRef) + } + + dataRef := verb.Request + + fmt.Printf("dataRef: %v\n", dataRef) + fmt.Printf("requestMap: %v\n", requestMap) + return validateRequestMap(dataRef, []string{dataRef.String()}, requestMap, sch) +} + // ValidateAndExtractBody validates the request body against the schema and extracts the request body as a JSON blob. func ValidateAndExtractBody(route *dal.IngressRoute, r *http.Request, sch *schema.Schema) ([]byte, error) { requestMap, err := buildRequestMap(route, r) diff --git a/go-runtime/compile/generate/go.work.tmpl b/go-runtime/compile/generate/go.work.tmpl index d8813076f5..e251ddf81a 100644 --- a/go-runtime/compile/generate/go.work.tmpl +++ b/go-runtime/compile/generate/go.work.tmpl @@ -1,4 +1,4 @@ -go 1.21.4 +go 1.21.5 use ( .