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

For OpenAPI, enable CORS. #17

Merged
merged 3 commits into from
Mar 14, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 33 additions & 27 deletions pkg/rest/apisurface.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ type APISurface struct {
// implementation for the different OSB API operations.
BusinessLogic broker.BusinessLogic
Metrics *metrics.OSBMetricsCollector
EnableCORS bool
}

// NewAPISurface returns a new, ready-to-go APISurface.
Expand All @@ -37,14 +38,19 @@ func NewAPISurface(businessLogic broker.BusinessLogic, m *metrics.OSBMetricsColl
return api, nil
}

// OptionsHandler deals with the OPTIONS type request allowing the client to gather the headers.
func (s *APISurface) OptionsHandler(w http.ResponseWriter, r *http.Request) {
s.writeResponse(w, http.StatusOK, nil)
}

// GetCatalogHandler is the mux handler that dispatches requests to get the
// broker's catalog to the broker's BusinessLogic.
func (s *APISurface) GetCatalogHandler(w http.ResponseWriter, r *http.Request) {
s.Metrics.Actions.WithLabelValues("get_catalog").Inc()

version := getBrokerAPIVersionFromRequest(r)
if err := s.BusinessLogic.ValidateBrokerAPIVersion(version); err != nil {
writeError(w, err, http.StatusPreconditionFailed)
s.writeError(w, err, http.StatusPreconditionFailed)
return
}

Expand All @@ -55,11 +61,11 @@ func (s *APISurface) GetCatalogHandler(w http.ResponseWriter, r *http.Request) {

response, err := s.BusinessLogic.GetCatalog(c)
if err != nil {
writeError(w, err, http.StatusInternalServerError)
s.writeError(w, err, http.StatusInternalServerError)
return
}

writeResponse(w, http.StatusOK, response)
s.writeResponse(w, http.StatusOK, response)
}

// ProvisionHandler is the mux handler that dispatches ProvisionRequests to the
Expand All @@ -69,13 +75,13 @@ func (s *APISurface) ProvisionHandler(w http.ResponseWriter, r *http.Request) {

version := getBrokerAPIVersionFromRequest(r)
if err := s.BusinessLogic.ValidateBrokerAPIVersion(version); err != nil {
writeError(w, err, http.StatusPreconditionFailed)
s.writeError(w, err, http.StatusPreconditionFailed)
return
}

request, err := unpackProvisionRequest(r)
if err != nil {
writeError(w, err, http.StatusBadRequest)
s.writeError(w, err, http.StatusBadRequest)
return
}

Expand All @@ -88,7 +94,7 @@ func (s *APISurface) ProvisionHandler(w http.ResponseWriter, r *http.Request) {

response, err := s.BusinessLogic.Provision(request, c)
if err != nil {
writeError(w, err, http.StatusInternalServerError)
s.writeError(w, err, http.StatusInternalServerError)
return
}

Expand All @@ -97,7 +103,7 @@ func (s *APISurface) ProvisionHandler(w http.ResponseWriter, r *http.Request) {
status = http.StatusAccepted
}

writeResponse(w, status, response)
s.writeResponse(w, status, response)
}

// unpackProvisionRequest unpacks an osb request from the given HTTP request.
Expand Down Expand Up @@ -135,13 +141,13 @@ func (s *APISurface) DeprovisionHandler(w http.ResponseWriter, r *http.Request)

version := getBrokerAPIVersionFromRequest(r)
if err := s.BusinessLogic.ValidateBrokerAPIVersion(version); err != nil {
writeError(w, err, http.StatusPreconditionFailed)
s.writeError(w, err, http.StatusPreconditionFailed)
return
}

request, err := unpackDeprovisionRequest(r)
if err != nil {
writeError(w, err, http.StatusInternalServerError)
s.writeError(w, err, http.StatusInternalServerError)
return
}

Expand All @@ -154,7 +160,7 @@ func (s *APISurface) DeprovisionHandler(w http.ResponseWriter, r *http.Request)

response, err := s.BusinessLogic.Deprovision(request, c)
if err != nil {
writeError(w, err, http.StatusInternalServerError)
s.writeError(w, err, http.StatusInternalServerError)
return
}

Expand All @@ -163,7 +169,7 @@ func (s *APISurface) DeprovisionHandler(w http.ResponseWriter, r *http.Request)
status = http.StatusAccepted
}

writeResponse(w, status, response)
s.writeResponse(w, status, response)
}

// unpackDeprovisionRequest unpacks an osb request from the given HTTP request.
Expand Down Expand Up @@ -195,15 +201,15 @@ func (s *APISurface) LastOperationHandler(w http.ResponseWriter, r *http.Request

version := getBrokerAPIVersionFromRequest(r)
if err := s.BusinessLogic.ValidateBrokerAPIVersion(version); err != nil {
writeError(w, err, http.StatusPreconditionFailed)
s.writeError(w, err, http.StatusPreconditionFailed)
return
}

request, err := unpackLastOperationRequest(r)
if err != nil {
// TODO: This should return a 400 in this case as it is either
// malformed or missing mandatory data, as per the OSB spec.
writeError(w, err, http.StatusInternalServerError)
s.writeError(w, err, http.StatusInternalServerError)
return
}

Expand All @@ -218,11 +224,11 @@ func (s *APISurface) LastOperationHandler(w http.ResponseWriter, r *http.Request
if err != nil {
// TODO: This should return a 400 in this case as it is either
// malformed or missing mandatory data, as per the OSB spec.
writeError(w, err, http.StatusInternalServerError)
s.writeError(w, err, http.StatusInternalServerError)
return
}

writeResponse(w, http.StatusOK, response)
s.writeResponse(w, http.StatusOK, response)
}

// unpackLastOperationRequest unpacks an osb request from the given HTTP request.
Expand Down Expand Up @@ -254,13 +260,13 @@ func (s *APISurface) BindHandler(w http.ResponseWriter, r *http.Request) {

version := getBrokerAPIVersionFromRequest(r)
if err := s.BusinessLogic.ValidateBrokerAPIVersion(version); err != nil {
writeError(w, err, http.StatusPreconditionFailed)
s.writeError(w, err, http.StatusPreconditionFailed)
return
}

request, err := unpackBindRequest(r)
if err != nil {
writeError(w, err, http.StatusInternalServerError)
s.writeError(w, err, http.StatusInternalServerError)
return
}

Expand All @@ -273,11 +279,11 @@ func (s *APISurface) BindHandler(w http.ResponseWriter, r *http.Request) {

response, err := s.BusinessLogic.Bind(request, c)
if err != nil {
writeError(w, err, http.StatusInternalServerError)
s.writeError(w, err, http.StatusInternalServerError)
return
}

writeResponse(w, http.StatusOK, response)
s.writeResponse(w, http.StatusOK, response)
}

// unpackBindRequest unpacks an osb request from the given HTTP request.
Expand Down Expand Up @@ -307,13 +313,13 @@ func (s *APISurface) UnbindHandler(w http.ResponseWriter, r *http.Request) {

version := getBrokerAPIVersionFromRequest(r)
if err := s.BusinessLogic.ValidateBrokerAPIVersion(version); err != nil {
writeError(w, err, http.StatusPreconditionFailed)
s.writeError(w, err, http.StatusPreconditionFailed)
return
}

request, err := unpackUnbindRequest(r)
if err != nil {
writeError(w, err, http.StatusInternalServerError)
s.writeError(w, err, http.StatusInternalServerError)
return
}

Expand All @@ -325,11 +331,11 @@ func (s *APISurface) UnbindHandler(w http.ResponseWriter, r *http.Request) {

response, err := s.BusinessLogic.Unbind(request, c)
if err != nil {
writeError(w, err, http.StatusInternalServerError)
s.writeError(w, err, http.StatusInternalServerError)
return
}

writeResponse(w, http.StatusOK, response)
s.writeResponse(w, http.StatusOK, response)
}

// unpackUnbindRequest unpacks an osb request from the given HTTP request.
Expand All @@ -356,13 +362,13 @@ func (s *APISurface) UpdateHandler(w http.ResponseWriter, r *http.Request) {

version := getBrokerAPIVersionFromRequest(r)
if err := s.BusinessLogic.ValidateBrokerAPIVersion(version); err != nil {
writeError(w, err, http.StatusPreconditionFailed)
s.writeError(w, err, http.StatusPreconditionFailed)
return
}

request, err := unpackUpdateRequest(r)
if err != nil {
writeError(w, err, http.StatusInternalServerError)
s.writeError(w, err, http.StatusInternalServerError)
return
}

Expand All @@ -375,7 +381,7 @@ func (s *APISurface) UpdateHandler(w http.ResponseWriter, r *http.Request) {

response, err := s.BusinessLogic.Update(request, c)
if err != nil {
writeError(w, err, http.StatusInternalServerError)
s.writeError(w, err, http.StatusInternalServerError)
return
}

Expand All @@ -384,7 +390,7 @@ func (s *APISurface) UpdateHandler(w http.ResponseWriter, r *http.Request) {
status = http.StatusAccepted
}

writeResponse(w, status, response)
s.writeResponse(w, status, response)
}

func unpackUpdateRequest(r *http.Request) (*osb.UpdateInstanceRequest, error) {
Expand Down
71 changes: 0 additions & 71 deletions pkg/rest/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,77 +12,6 @@ func getBrokerAPIVersionFromRequest(r *http.Request) string {
return r.Header.Get(osb.APIVersionHeader)
}

// writeResponse will serialize 'object' to the HTTP ResponseWriter
// using the 'code' as the HTTP status code
func writeResponse(w http.ResponseWriter, code int, object interface{}) {
data, err := json.Marshal(object)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}

w.Header().Set("Content-Type", "application/json")
w.WriteHeader(code)
w.Write(data)
}

// writeError accepts any error and writes it to the given ResponseWriter along
// with a status code.
//
// If the error is an osb.HTTPStatusCodeError, the error's StatusCode field will
// be used and the response body will contain the error's Description and
// ErrorMessage fields (if set).
//
// Otherwise, the given defaultStatusCode will be used, and the response body
// will have the result of calling the error's Error method set in the
// 'description' field.
//
// For more information about OSB errors, see:
//
// https://github.com/openservicebrokerapi/servicebroker/blob/master/spec.md#service-broker-errors
func writeError(w http.ResponseWriter, err error, defaultStatusCode int) {
if httpErr, ok := osb.IsHTTPError(err); ok {
writeOSBStatusCodeErrorResponse(w, httpErr)
return
}

writeErrorResponse(w, defaultStatusCode, err)
}

// writeOSBStatusCodeErrorResponse writes the given HTTPStatusCodeError to the
// given ResponseWriter. The HTTP response's status code is the error's
// StatusCode field and the body contains the ErrorMessage and Description
// fields, if set.
func writeOSBStatusCodeErrorResponse(w http.ResponseWriter, err *osb.HTTPStatusCodeError) {
type e struct {
ErrorMessage *string `json:"error,omitempty"`
Description *string `json:"description,omitempty"`
}

body := &e{}
if err.Description != nil {
body.Description = err.Description
}

if err.ErrorMessage != nil {
body.ErrorMessage = err.ErrorMessage
}

writeResponse(w, err.StatusCode, body)
}

// writeErrorResponse writes the given status code and error to the given
// ResponseWriter. The response body will be a json object with the field
// 'description' set from calling Error() on the passed-in error.
func writeErrorResponse(w http.ResponseWriter, code int, err error) {
type e struct {
Description string `json:"description"`
}
writeResponse(w, code, &e{
Description: err.Error(),
})
}

func unmarshalRequestBody(request *http.Request, obj interface{}) error {
body, err := ioutil.ReadAll(request.Body)
if err != nil {
Expand Down
Loading