Skip to content

Commit

Permalink
Merge pull request #9 from retr0h/issue/8
Browse files Browse the repository at this point in the history
Ability to go embed schema
  • Loading branch information
alexferl authored Oct 2, 2024
2 parents e84fc2f + 5575164 commit 0f1b8f1
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 3 deletions.
30 changes: 27 additions & 3 deletions openapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@ type Config struct {
// Required.
Schema string

// SchemaBytes allows loading the OpenAPI specification directly
// from a byte slice ([]byte). This is useful for embedding the
// OpenAPI spec in the binary using Go's embed package, or if the
// spec is obtained dynamically at runtime.
// Required unless Schema is provided.
//
// If both Schema and SchemaBytes are provided, SchemaBytes takes precedence.
SchemaBytes []byte

// ContextKey defines the key that will be used to store the validator
// on the echo.Context when the request is successfully validated.
// Optional. Defaults to "validator".
Expand All @@ -46,13 +55,19 @@ func OpenAPI(file string) echo.MiddlewareFunc {
return OpenAPIWithConfig(c)
}

func OpenAPIFromBytes(schemaBytes []byte) echo.MiddlewareFunc {
c := DefaultConfig
c.SchemaBytes = schemaBytes
return OpenAPIWithConfig(c)
}

func OpenAPIWithConfig(config Config) echo.MiddlewareFunc {
if config.Skipper == nil {
config.Skipper = DefaultConfig.Skipper
}

if config.Schema == "" {
panic("schema is required")
if config.Schema == "" && len(config.SchemaBytes) == 0 {
panic("either schema or schemaBytes is required")
}

if config.ContextKey == "" {
Expand All @@ -61,7 +76,16 @@ func OpenAPIWithConfig(config Config) echo.MiddlewareFunc {

ctx := context.Background()
loader := &openapi3.Loader{Context: ctx, IsExternalRefsAllowed: true}
schema, err := loader.LoadFromFile(config.Schema)

var schema *openapi3.T
var err error

if len(config.SchemaBytes) > 0 {
schema, err = loader.LoadFromData(config.SchemaBytes)
} else {
schema, err = loader.LoadFromFile(config.Schema)
}

if err != nil {
panic(fmt.Sprintf("failed loading schema file: %v", err))
}
Expand Down
96 changes: 96 additions & 0 deletions openapi_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,3 +217,99 @@ func TestOpenAPIWithConfig_Request_Validation(t *testing.T) {
})
}
}

func TestOpenAPIFromBytes(t *testing.T) {
sampleOpenAPISpec := []byte(`
openapi: 3.0.0
info:
title: Sample API
version: "1.0"
paths:
/:
get:
responses:
'200':
description: OK
/validation:
post:
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
username:
type: string
minLength: 2
responses:
'200':
description: OK
`)

testCases := []struct {
name string
method string
path string
body *bytes.Buffer
statusCode int
contentType string
}{
{
name: "valid GET request to /",
method: http.MethodGet,
path: "/",
body: nil, // No body for GET requests
statusCode: http.StatusOK,
},
{
name: "invalid POST request to /validation with empty body",
method: http.MethodPost,
path: "/validation",
body: bytes.NewBuffer([]byte(``)),
statusCode: http.StatusBadRequest,
contentType: echo.MIMEApplicationJSON,
},
{
name: "valid POST request to /validation",
method: http.MethodPost,
path: "/validation",
body: bytes.NewBuffer([]byte(`{"username": "test"}`)),
statusCode: http.StatusOK,
contentType: echo.MIMEApplicationJSON,
},
}

e := echo.New()

e.Any("/", func(c echo.Context) error {
return c.JSON(http.StatusOK, "ok")
})

e.Any("/validation", func(c echo.Context) error {
return c.JSON(http.StatusOK, "ok")
})

e.Use(OpenAPIFromBytes(sampleOpenAPISpec))

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
var req *http.Request

if tc.body == nil {
req = httptest.NewRequest(tc.method, tc.path, http.NoBody)
} else {
req = httptest.NewRequest(tc.method, tc.path, tc.body)
}

if tc.contentType != "" {
req.Header.Set("Content-Type", tc.contentType)
}

resp := httptest.NewRecorder()
e.ServeHTTP(resp, req)

assert.Equal(t, tc.statusCode, resp.Code)
})
}
}

0 comments on commit 0f1b8f1

Please sign in to comment.