Skip to content

Commit

Permalink
Add OpenAPI SecurityMiddleware facade (#30)
Browse files Browse the repository at this point in the history
  • Loading branch information
vearutop authored Mar 20, 2021
1 parent 1928f91 commit f95971d
Show file tree
Hide file tree
Showing 8 changed files with 99 additions and 40 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ ifeq ($(DEVGO_PATH),)
endif

-include $(DEVGO_PATH)/makefiles/main.mk
-include $(DEVGO_PATH)/makefiles/lint.mk
-include $(DEVGO_PATH)/makefiles/test-unit.mk
-include $(DEVGO_PATH)/makefiles/bench.mk
-include $(DEVGO_PATH)/makefiles/lint.mk
-include $(DEVGO_PATH)/makefiles/github-actions.mk
-include $(DEVGO_PATH)/makefiles/reset-ci.mk

## Run tests
test: test-unit test-examples
Expand Down
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -365,4 +365,11 @@ func main() {

```

![Documentation Page](./_examples/basic/screen.png)
![Documentation Page](./_examples/basic/screen.png)

## Versioning

This project adheres to [Semantic Versioning](https://semver.org/#semantic-versioning-200).

Before version `1.0.0`, breaking changes are tagged with `MINOR` bump, features and fixes are tagged with `PATCH` bump.
After version `1.0.0`, breaking changes are tagged with `MAJOR` bump.
3 changes: 1 addition & 2 deletions chirouter/wrapper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ type HandlerWithBar struct {
func (h HandlerWithBar) Bar() {}

func (h HandlerWithBar) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
_, err := rw.Write([]byte("bar"))
if err != nil {
if _, err := rw.Write([]byte("bar")); err != nil {
panic(err)
}

Expand Down
3 changes: 3 additions & 0 deletions dev_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package rest_test

import _ "github.com/bool64/dev" // Include CI/Dev scripts to project.
57 changes: 57 additions & 0 deletions nethttp/example_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package nethttp_test

import (
"context"
"net/http"

"github.com/go-chi/chi"
"github.com/swaggest/openapi-go/openapi3"
"github.com/swaggest/rest/chirouter"
"github.com/swaggest/rest/nethttp"
"github.com/swaggest/rest/openapi"
"github.com/swaggest/usecase"
)

func ExampleSecurityMiddleware() {
// Create router.
r := chirouter.NewWrapper(chi.NewRouter())

// Init API documentation schema.
apiSchema := &openapi.Collector{}

// Setup middlewares (non-documentary middlewares omitted for brevity).
r.Use(
nethttp.OpenAPIMiddleware(apiSchema), // Documentation collector.
)

// Configure an actual security middleware.
serviceTokenAuth := func(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
if req.Header.Get("Authorization") != "<secret>" {
http.Error(w, "Authentication failed.", http.StatusUnauthorized)

return
}

h.ServeHTTP(w, req)
})
}

// Configure documentation middleware to describe actual security middleware.
serviceTokenDoc := nethttp.SecurityMiddleware(apiSchema, "serviceToken", openapi3.SecurityScheme{
APIKeySecurityScheme: &openapi3.APIKeySecurityScheme{
Name: "Authorization",
In: openapi3.APIKeySecuritySchemeInHeader,
},
})

u := usecase.NewIOI(nil, nil, func(ctx context.Context, input, output interface{}) error {
// Do something.
return nil
})

// Add use case handler to router with security middleware.
r.
With(serviceTokenAuth, serviceTokenDoc). // Apply a pair of middlewares: actual security and documentation.
Method(http.MethodGet, "/foo", nethttp.NewHandler(u))
}
57 changes: 27 additions & 30 deletions nethttp/openapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,26 +35,17 @@ func OpenAPIMiddleware(s *openapi.Collector) func(http.Handler) http.Handler {
}
}

// HTTPBasicSecurityMiddleware creates middleware to expose Basic Security schema.
func HTTPBasicSecurityMiddleware(
// SecurityMiddleware creates middleware to expose security scheme.
func SecurityMiddleware(
c *openapi.Collector,
name, description string,
name string,
scheme openapi3.SecurityScheme,
options ...func(*MiddlewareConfig),
) func(http.Handler) http.Handler {
hss := openapi3.HTTPSecurityScheme{}

hss.WithScheme("basic")

if description != "" {
hss.WithDescription(description)
}

c.Reflector().SpecEns().ComponentsEns().SecuritySchemesEns().WithMapOfSecuritySchemeOrRefValuesItem(
name,
openapi3.SecuritySchemeOrRef{
SecurityScheme: &openapi3.SecurityScheme{
HTTPSecurityScheme: &hss,
},
SecurityScheme: &scheme,
},
)

Expand All @@ -67,6 +58,25 @@ func HTTPBasicSecurityMiddleware(
return securityMiddleware(c, name, cfg)
}

// HTTPBasicSecurityMiddleware creates middleware to expose Basic Security schema.
func HTTPBasicSecurityMiddleware(
c *openapi.Collector,
name, description string,
options ...func(*MiddlewareConfig),
) func(http.Handler) http.Handler {
hss := openapi3.HTTPSecurityScheme{}

hss.WithScheme("basic")

if description != "" {
hss.WithDescription(description)
}

return SecurityMiddleware(c, name, openapi3.SecurityScheme{
HTTPSecurityScheme: &hss,
}, options...)
}

// HTTPBearerSecurityMiddleware creates middleware to expose HTTP Bearer security schema.
func HTTPBearerSecurityMiddleware(
c *openapi.Collector,
Expand All @@ -85,22 +95,9 @@ func HTTPBearerSecurityMiddleware(
hss.WithDescription(description)
}

c.Reflector().SpecEns().ComponentsEns().SecuritySchemesEns().WithMapOfSecuritySchemeOrRefValuesItem(
name,
openapi3.SecuritySchemeOrRef{
SecurityScheme: &openapi3.SecurityScheme{
HTTPSecurityScheme: &hss,
},
},
)

cfg := MiddlewareConfig{}

for _, o := range options {
o(&cfg)
}

return securityMiddleware(c, name, cfg)
return SecurityMiddleware(c, name, openapi3.SecurityScheme{
HTTPSecurityScheme: &hss,
}, options...)
}

// AnnotateOpenAPI applies OpenAPI annotation to relevant handlers.
Expand Down
3 changes: 1 addition & 2 deletions response/gzip/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,7 @@ func maybeGzipResponseWriter(w http.ResponseWriter, r *http.Request) http.Respon

ae = strings.ToLower(ae)

n := strings.Index(ae, "gzip")
if n < 0 {
if n := strings.Index(ae, "gzip"); n < 0 {
return w
}

Expand Down
3 changes: 0 additions & 3 deletions tools_test.go

This file was deleted.

0 comments on commit f95971d

Please sign in to comment.