Skip to content

Commit

Permalink
Allow URL-encoded paths via options pattern (#178)
Browse files Browse the repository at this point in the history
* test: improve message for incorrect HTTP response

* feat: introduce constructor using options pattern

- the options pattern allows for confiuration without the complexity of
multiple constructors
- the original constructors have been marked deprecated but are still
available. Under the hood they call the new constructor.

* feat: allow URL-encoded paths

This allows a service instance ID or binding ID to contain URL-encoded
data

* Keep attachRouts uchanged

Co-authored-by: Marcela Campo <[email protected]>
  • Loading branch information
blgm and FelisiaM authored Sep 20, 2021
1 parent 14af36f commit 0f775ba
Show file tree
Hide file tree
Showing 3 changed files with 258 additions and 128 deletions.
24 changes: 6 additions & 18 deletions api.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,7 @@ import (

"code.cloudfoundry.org/lager"
"github.com/gorilla/mux"
"github.com/pivotal-cf/brokerapi/v8/auth"
"github.com/pivotal-cf/brokerapi/v8/handlers"
"github.com/pivotal-cf/brokerapi/v8/middlewares"
)

type BrokerCredentials struct {
Expand All @@ -31,28 +29,18 @@ type BrokerCredentials struct {
}

func New(serviceBroker ServiceBroker, logger lager.Logger, brokerCredentials BrokerCredentials) http.Handler {
authMiddleware := auth.NewWrapper(brokerCredentials.Username, brokerCredentials.Password).Wrap
return NewWithCustomAuth(serviceBroker, logger, authMiddleware)
return NewWithOptions(serviceBroker, logger, WithBrokerCredentials(brokerCredentials))
}

func NewWithCustomAuth(serviceBroker ServiceBroker, logger lager.Logger, authMiddleware mux.MiddlewareFunc) http.Handler {
router := mux.NewRouter()

AttachRoutes(router, serviceBroker, logger)

apiVersionMiddleware := middlewares.APIVersionMiddleware{LoggerFactory: logger}

router.Use(middlewares.AddCorrelationIDToContext)
router.Use(authMiddleware)
router.Use(middlewares.AddOriginatingIdentityToContext)
router.Use(apiVersionMiddleware.ValidateAPIVersionHdr)
router.Use(middlewares.AddInfoLocationToContext)
router.Use(middlewares.AddRequestIdentityToContext)

return router
return NewWithOptions(serviceBroker, logger, WithCustomAuth(authMiddleware))
}

func AttachRoutes(router *mux.Router, serviceBroker ServiceBroker, logger lager.Logger) {
attachRoutes(router, serviceBroker, logger)
}

func attachRoutes(router *mux.Router, serviceBroker ServiceBroker, logger lager.Logger) {
apiHandler := handlers.NewApiHandler(serviceBroker, logger)
router.HandleFunc("/v2/catalog", apiHandler.Catalog).Methods("GET")

Expand Down
95 changes: 95 additions & 0 deletions api_options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// Copyright (C) 2015-Present Pivotal Software, Inc. All rights reserved.

// This program and the accompanying materials are made available under
// the terms of the under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

// http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package brokerapi

import (
"net/http"

"code.cloudfoundry.org/lager"
"github.com/gorilla/mux"
"github.com/pivotal-cf/brokerapi/v8/auth"
"github.com/pivotal-cf/brokerapi/v8/domain"
"github.com/pivotal-cf/brokerapi/v8/middlewares"
)

func NewWithOptions(serviceBroker domain.ServiceBroker, logger lager.Logger, opts ...Option) http.Handler {
cfg := newDefaultConfig(logger)
WithOptions(append(opts, withDefaultMiddleware())...)(cfg)
attachRoutes(cfg.router, serviceBroker, logger)

return cfg.router
}

type Option func(*config)

func WithRouter(router *mux.Router) Option {
return func(c *config) {
c.router = router
c.customRouter = true
}
}

func WithBrokerCredentials(brokerCredentials BrokerCredentials) Option {
return func(c *config) {
c.router.Use(auth.NewWrapper(brokerCredentials.Username, brokerCredentials.Password).Wrap)
}
}

func WithCustomAuth(authMiddleware mux.MiddlewareFunc) Option {
return func(c *config) {
c.router.Use(authMiddleware)
}
}

func WithEncodedPath() Option {
return func(c *config) {
c.router.UseEncodedPath()
}
}

func withDefaultMiddleware() Option {
return func(c *config) {
if !c.customRouter {
c.router.Use(middlewares.APIVersionMiddleware{LoggerFactory: c.logger}.ValidateAPIVersionHdr)
c.router.Use(middlewares.AddCorrelationIDToContext)
c.router.Use(middlewares.AddOriginatingIdentityToContext)
c.router.Use(middlewares.AddInfoLocationToContext)
c.router.Use(middlewares.AddRequestIdentityToContext)
}
}
}

func WithOptions(opts ...Option) Option {
return func(c *config) {
for _, o := range opts {
o(c)
}
}
}

func newDefaultConfig(logger lager.Logger) *config {
return &config{
router: mux.NewRouter(),
customRouter: false,
logger: logger,
}
}

type config struct {
router *mux.Router
customRouter bool
logger lager.Logger
}
Loading

0 comments on commit 0f775ba

Please sign in to comment.