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

Fixed embedded spec; correctly resolve external references of embedded spec in the runtime #320

Closed
wants to merge 2 commits into from

Conversation

dududko
Copy link
Contributor

@dududko dududko commented Mar 18, 2021

Intro

A feature that I added last summer (the --import-mapping option) was not complete, because it breaks the embedded spec feature, thus many users can not use the advantage of request validation based on openapi spec for echo.

This pull request contains the proposal of how this could be fixed.

Solution

To solve this issue we need to embed the original spec inside the golang package. This was already implemented before, but now in go 1.16 it can be done in a single line using a go directive //go:embed <path_to_file>. The only downside of this approach is that we need to store the embedded file in the same package (or in child packages), otherwise go compiler will fail. I think it should be easy to implement.

Next, to resolve all external references, we need to have an abstract file system, which knows about all direct and transitive external references. A function func PathToRawSpec(pathPrefix string) map[string]func() []byte { does this. It returns to a caller a map of all dependencies by asking a map of dependencies from direct dependencies and merging them in single map. This function is generated.

Basically this is it. By calling GetSwagger function you will receive a valid openapi spec container with properly resolved external references. But of course all external references need to be the pre-existing golang packages.

In my case I have multiple openapi specs which are served by the same web server. This is why the swagger containers which I get from GetSwagger function need to be merged together. I found out that for request validator it is enough to merge just paths. So I added a helper function for this. https://github.com/dududko/oapi-codegen/blob/embed-spec/pkg/util/merge.go#L36-L59

Example

Here is the example of how to enable the request validation in the source code of your project.

package main

import (
	"github.com/deepmap/oapi-codegen/pkg/middleware"
	"github.com/deepmap/oapi-codegen/blob/embed-spec/pkg/util"
	"github.com/labstack/echo/v4"

	"github.com/dududko/example/packageA"
	"github.com/dududko/example/packageB"
)

func main() {
	swagger, err := utils.MergeAll(ctx, packageA.GetSwagger, packageB.GetSwagger)

	e := echo.New()
	e.Use(middleware.OapiRequestValidator(swagger))
}

This was referenced Mar 18, 2021
@deepmap-marcinr
Copy link
Contributor

We have users on older versions of Go, we can't pull in 1.16 as a dependency yet.

@dududko
Copy link
Contributor Author

dududko commented Mar 24, 2021

I understand this. Will return back the old embedding mechanics and prepare a new PR.
Actually the old embedding approach will make the changes more transparent and easier to test and integrate.

@wangyoucao577
Copy link
Contributor

@dududko looks pretty good! Thanks very much!
One question: is it possible to resolve external reference via the base64 encoded swaggerSpec rather than file? So that no file need to be embedded, and no go1.16 needed.

@dududko dududko mentioned this pull request Mar 26, 2021
@dududko
Copy link
Contributor Author

dududko commented Mar 26, 2021

@wangyoucao577 I prepared a new PR with base64 encoded spec files #327.

@dududko
Copy link
Contributor Author

dududko commented Apr 4, 2021

Closed in favor of #327

@dududko dududko closed this Apr 4, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants