diff --git a/backend/controller/console.go b/backend/controller/console.go index 6d08cd0c1b..513124d125 100644 --- a/backend/controller/console.go +++ b/backend/controller/console.go @@ -44,15 +44,14 @@ func visitNode(sch *schema.Schema, n schema.Node, verbString *string) error { return schema.Visit(n, func(n schema.Node, next func() error) error { switch n := n.(type) { case *schema.Ref: - decl, ok := sch.Resolve(n).Get() - if !ok { - return fmt.Errorf("failed to resolve %s", n) - } - *verbString += decl.String() + "\n\n" - err := visitNode(sch, decl, verbString) - if err != nil { - return err + if decl, ok := sch.Resolve(n).Get(); ok { + *verbString += decl.String() + "\n\n" + err := visitNode(sch, decl, verbString) + if err != nil { + return err + } } + default: } return next() diff --git a/backend/controller/console_test.go b/backend/controller/console_test.go index 0ecd23d690..7d6b3465d7 100644 --- a/backend/controller/console_test.go +++ b/backend/controller/console_test.go @@ -13,10 +13,20 @@ func TestVerbSchemaString(t *testing.T) { Request: &schema.Ref{Module: "foo", Name: "EchoRequest"}, Response: &schema.Ref{Module: "foo", Name: "EchoResponse"}, } + ingressVerb := &schema.Verb{ + Name: "Ingress", + Request: &schema.Ref{Module: "builtin", Name: "HttpRequest", TypeParameters: []schema.Type{&schema.String{}}}, + Response: &schema.Ref{Module: "builtin", Name: "HttpResponse", TypeParameters: []schema.Type{&schema.String{}, &schema.String{}}}, + Metadata: []schema.Metadata{ + &schema.MetadataIngress{Type: "http", Method: "GET", Path: []schema.IngressPathComponent{&schema.IngressPathLiteral{Text: "test"}}}, + }, + } sch := &schema.Schema{ Modules: []*schema.Module{ + schema.Builtins(), {Name: "foo", Decls: []schema.Decl{ verb, + ingressVerb, &schema.Data{ Name: "EchoRequest", Fields: []*schema.Field{ @@ -51,6 +61,7 @@ func TestVerbSchemaString(t *testing.T) { }}, {Name: "bar", Decls: []schema.Decl{ verb, + ingressVerb, &schema.Data{ Name: "BarData", Export: true, @@ -92,3 +103,68 @@ verb Echo(foo.EchoRequest) foo.EchoResponse` assert.NoError(t, err) assert.Equal(t, expected, schemaString) } + +func TestVerbSchemaStringIngress(t *testing.T) { + verb := &schema.Verb{ + Name: "Ingress", + Request: &schema.Ref{Module: "builtin", Name: "HttpRequest", TypeParameters: []schema.Type{&schema.Ref{Module: "foo", Name: "FooRequest"}}}, + Response: &schema.Ref{Module: "builtin", Name: "HttpResponse", TypeParameters: []schema.Type{&schema.Ref{Module: "foo", Name: "FooResponse"}, &schema.String{}}}, + Metadata: []schema.Metadata{ + &schema.MetadataIngress{Type: "http", Method: "GET", Path: []schema.IngressPathComponent{&schema.IngressPathLiteral{Text: "foo"}}}, + }, + } + sch := &schema.Schema{ + Modules: []*schema.Module{ + schema.Builtins(), + {Name: "foo", Decls: []schema.Decl{ + verb, + &schema.Data{ + Name: "FooRequest", + Fields: []*schema.Field{ + {Name: "Name", Type: &schema.String{}}, + }, + }, + &schema.Data{ + Name: "FooResponse", + Fields: []*schema.Field{ + {Name: "Message", Type: &schema.String{}}, + }, + }, + }}, + }, + } + + expected := `// HTTP request structure used for HTTP ingress verbs. +export data HttpRequest
{ + method String + path String + pathParameters {String: String} + query {String: [String]} + headers {String: [String]} + body Body +} + +data FooRequest { + Name String +} + +// HTTP response structure used for HTTP ingress verbs. +export data HttpResponse { + status Int + headers {String: [String]} + // Either "body" or "error" must be present, not both. + body Body? + error Error? +} + +data FooResponse { + Message String +} + +verb Ingress(builtin.HttpRequest