huma icon indicating copy to clipboard operation
huma copied to clipboard

Support for multiple response objects?

Open carlmontanari opened this issue 2 years ago • 1 comments

Howdy fellow Pacific Northwest person 👋 ⛰️

I found huma while looking for something FastAPI-like but in Go, and wow, thanks so much for this project! This really fits my brain and I love not having to have a billion comments in order to get swaggo to build out OpenAPI spec for me.

I'm wondering how you feel about supporting multiple return types (anyOf, oneOf) (as supported in OpenAPI v3 linky)? It seems that this is not the most popular idea and looks like it got shot down in an issue on swaggo (also I guess they are supporting v2 only at this point?). Basically I have an API that I'd like to have return very slightly different payloads but I would really like the docs to show both (or however many) options that the endpoint could return.

I hacked around a bit and was able to get this output which is what I'm looking for more or less:

Screen Shot 2022-03-26 at 3 26 48 PM

Setting the oneOf models is handled like:

	note.Get("get-note", "Get a note by its ID",
		responses.OK().ModelsOneOf(NoteWrapper{}, []string{}, huma.ErrorModel{}),
		responses.NotFound(),
	).Run(func(ctx huma.Context, input NoteIDParam) {
		if n, ok := memoryDB.Load(input.NoteID); ok {
			// Note with that ID exists!
			ctx.WriteModel(http.StatusOK, n.(Note))
			return
		}

		ctx.WriteError(http.StatusNotFound, "Note "+input.NoteID+" not found")
	})

Obviously I added the ModlesOneOf method to Response.

Is this something you'd be interested in supporting? If not, I totally get it but figured I'd ask! If yes, I can get a PR cleaned up and raised shortly!

Thanks a bunch!

Carl

carlmontanari avatar Mar 26 '22 22:03 carlmontanari

@carlmontanari it's not something I generally want to encourage in my own APIs because it makes things kind of complicated on the consuming client, but I'm totally open to supporting this in Huma in some way.

I've been playing with Go 1.18 generics and am wondering how this might work with those. I'll push up a new package that sits on top of Huma so people can opt-in to 1.18 features shortly and maybe we could discuss?

danielgtaylor avatar Apr 14 '22 22:04 danielgtaylor

BTW, the Huma v2 beta has been released, and while this functionality is not directly built-in to the library it is now possible to do just by setting a custom schema and making the body an any, as in the linked PR #147.

Feel free to check out Huma v2 and play around with it, and let me know if you have any ideas on how to make it easier to use.

Lastly, on the input side you can also support polymorphism, see the example at https://github.com/danielgtaylor/huma/issues/128#issuecomment-1725939367. In either case you lose some of the Huma magic, but it's possible if needed for a specific call in the API. It may even be possible to piggyback on #145 to make some kind of OneOf[...] generic type to encapsulate some of this.

danielgtaylor avatar Oct 20 '23 23:10 danielgtaylor