Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

how to return an existing type plus additional cookies ? #3367

Closed
zig opened this issue Sep 27, 2023 · 6 comments · Fixed by #3379
Closed

how to return an existing type plus additional cookies ? #3367

zig opened this issue Sep 27, 2023 · 6 comments · Fixed by #3379
Labels

Comments

@zig
Copy link

zig commented Sep 27, 2023

Here's an example design :

package design

import . "goa.design/goa/v3/dsl"

var _ = API("test", func() {
	Server("test", func() {
		Host("localhost", func() { URI("http://localhost:8088") })
	})
})

func _Instance() {
	Attribute("sessionId", String)
	Required("sessionId")
}

var Instance = Type("Instance", _Instance)
var InstanceWithCookies = Type("InstanceWithCookies", func() {
	Extend(Instance)
	//_Instance()

	Attribute("cookie", String)
})

var _ = Service("ud", func() {
	HTTP(func() {
		Path("/api")
	})

	Method("newInstance", func() {
		Result(InstanceWithCookies)
		HTTP(func() {
			POST("/instance")
			Response(StatusOK, func() {
				Cookie("cookie")
				CookieMaxAge(3600 * 24 * 365)
				CookieSecure()
				CookieHTTPOnly()
				CookiePath("/")
			})
		})
	})

	Method("listInstances", func() {
		Result(ArrayOf(Instance))

		HTTP(func() {
			GET("/instances")
			Response(StatusOK)
		})
	})

})

I define 'Instance' type, which is returned by a 'newInstance' and 'listInstances', but I want 'newInstance' to also define a cookie. So I derived a type InstanceWithCookies from 'Instance', however things don't happen as expected, only 'InstanceWithCookies' is defined and used in the resulted generated code and openapi, which is weird.
Is there another way to return some existing type + cookies without deriving a new type ?

@raphael
Copy link
Member

raphael commented Sep 29, 2023

This seems to be a bug in the OpenAPI generation, the newInstance operation should use the type Instance and not InstanceWithCookies.

@raphael raphael added the bug label Sep 29, 2023
@zig
Copy link
Author

zig commented Sep 29, 2023

I also notice that returned (set) cookies are not documented in the openapi.

Maybe what we would need in this case, instead of defining (extend) a new type with cookies, which is a bit weird (and define a new type name), would be to be able to define Result as the combination of several things, in this case it would be 'Instance' + the cookie. It would kind of merge all these in an anonymous type.

But right now if I try to do this :

	Method("newInstance2", func() {
		Result(Instance, func() {
			Attribute("cookie", String)
		})
		HTTP(func() {
			POST("/instance2")
			Response(StatusOK, func() {
				Cookie("cookie")
				CookieMaxAge(3600 * 24 * 365)
				CookieSecure()
				CookieHTTPOnly()
				CookiePath("/")
			})
		})
	})

I get this error : [design/test.go:45] can't define child attribute "cookie" on attribute of type Instance *expr.UserTypeExpr in attribute

@raphael
Copy link
Member

raphael commented Sep 29, 2023

Yeah the above isn't valid DSL. Extend should work and would be the proper way to do what you want. For now though you could use your own function that defines the same attributes in two different types and add an additional cookie attribute to the InstanceWithCookies type.

@zig
Copy link
Author

zig commented Sep 29, 2023

The example I provided also has in comment the method you suggest where I use a function instead of Extend, but this leads to the same bug, where only InstanceWithCookies is defined in the openapi.

@raphael
Copy link
Member

raphael commented Sep 30, 2023

Thanks for the repro, this is fixed in #3379, a few things to note though:

  1. The fact that only one type is being generated is correct and by design. That is because the shape of the response bodies for both API endpoints are actually the exact same and Goa ensures that it won't create arbitrary schemas for types that are structurally identical. Meta("openapi:typename") can be used to override the name generated in the OpenAPI specification (Goa will use the name of the first type from which the body is derived by default).
  2. The OpenAPI specification does not define a discrete attribute for cookies in responses (it does for cookies in requests). Instead official examples add the "Set-Coookie" header so this is what the PR linked above does.

@zig
Copy link
Author

zig commented Oct 4, 2023

Thanks for the fix and explanations :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants