diff --git a/pkg/httputil/httputil.go b/pkg/httputil/httputil.go new file mode 100644 index 00000000..9c092b3c --- /dev/null +++ b/pkg/httputil/httputil.go @@ -0,0 +1,120 @@ +package httputil + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "net/http" + "net/url" + "strings" + + "github.com/go-kit/kit/log" + httptransport "github.com/go-kit/kit/transport/http" + "github.com/gorilla/mux" +) + +func NewRouter(logger log.Logger) (*mux.Router, []httptransport.ServerOption) { + r := mux.NewRouter() + options := []httptransport.ServerOption{ + httptransport.ServerErrorEncoder(ErrorEncoder), + httptransport.ServerErrorLogger(logger), + } + return r, options +} + +func EncodeJSONResponse(ctx context.Context, w http.ResponseWriter, response interface{}) error { + if f, ok := response.(failer); ok && f.Failed() != nil { + ErrorEncoder(ctx, f.Failed(), w) + return nil + } + w.Header().Set("Content-Type", "application/json; charset=utf-8") + if headerer, ok := response.(httptransport.Headerer); ok { + for k := range headerer.Headers() { + w.Header().Set(k, headerer.Headers().Get(k)) + } + } + code := http.StatusOK + if sc, ok := response.(httptransport.StatusCoder); ok { + code = sc.StatusCode() + } + w.WriteHeader(code) + + enc := json.NewEncoder(w) + enc.SetIndent("", " ") + return enc.Encode(response) +} + +func ErrorEncoder(_ context.Context, err error, w http.ResponseWriter) { + w.Header().Set("Content-Type", "application/json; charset=utf-8") + errMap := map[string]interface{}{"error": err.Error()} + enc := json.NewEncoder(w) + enc.SetIndent("", " ") + + if headerer, ok := err.(httptransport.Headerer); ok { + for k := range headerer.Headers() { + w.Header().Set(k, headerer.Headers().Get(k)) + } + } + + code := http.StatusInternalServerError + if sc, ok := err.(httptransport.StatusCoder); ok { + code = sc.StatusCode() + } + w.WriteHeader(code) + + enc.Encode(errMap) +} + +// failer is an interface that should be implemented by response types. +// Response encoders can check if responses are Failer, and if so if they've +// failed, and if so encode them using a separate write path based on the error. +type failer interface { + Failed() error +} + +type errorWrapper struct { + Error string `json:"error"` +} + +func JSONErrorDecoder(r *http.Response) error { + contentType := r.Header.Get("Content-Type") + if !strings.Contains(contentType, "application/json") { + return fmt.Errorf("expected JSON formatted error, got Content-Type %s", contentType) + } + var w errorWrapper + if err := json.NewDecoder(r.Body).Decode(&w); err != nil { + return err + } + return errors.New(w.Error) +} + +func EncodeRequestWithToken(token string, next httptransport.EncodeRequestFunc) httptransport.EncodeRequestFunc { + return func(ctx context.Context, r *http.Request, request interface{}) error { + r.SetBasicAuth("micromdm", token) + return next(ctx, r, request) + } +} + +func CopyURL(base *url.URL, path string) *url.URL { + next := *base + next.Path = path + return &next +} + +func DecodeJSONRequest(r *http.Request, into interface{}) error { + defer r.Body.Close() + err := json.NewDecoder(r.Body).Decode(into) + return err +} + +func DecodeJSONResponse(r *http.Response, into interface{}) error { + defer r.Body.Close() + + if r.StatusCode != http.StatusOK { + return JSONErrorDecoder(r) + } + + err := json.NewDecoder(r.Body).Decode(into) + return err +} diff --git a/platform/blueprint/apply_blueprint.go b/platform/blueprint/apply_blueprint.go index c47307d3..7060b08e 100644 --- a/platform/blueprint/apply_blueprint.go +++ b/platform/blueprint/apply_blueprint.go @@ -2,10 +2,10 @@ package blueprint import ( "context" - "encoding/json" "net/http" "github.com/go-kit/kit/endpoint" + "github.com/micromdm/micromdm/pkg/httputil" ) func (svc *BlueprintService) ApplyBlueprint(ctx context.Context, bp *Blueprint) error { @@ -20,22 +20,17 @@ type applyBlueprintResponse struct { Err error `json:"err,omitempty"` } -func (r applyBlueprintResponse) error() error { return r.Err } +func (r applyBlueprintResponse) Failed() error { return r.Err } func decodeApplyBlueprintRequest(ctx context.Context, r *http.Request) (interface{}, error) { - var bpReq applyBlueprintRequest - if err := json.NewDecoder(r.Body).Decode(&bpReq); err != nil { - return nil, err - } - return bpReq, nil + var req applyBlueprintRequest + err := httputil.DecodeJSONRequest(r, &req) + return req, err } func decodeApplyBlueprintResponse(_ context.Context, r *http.Response) (interface{}, error) { - if r.StatusCode != http.StatusOK { - return nil, errorDecoder(r) - } var resp applyBlueprintResponse - err := json.NewDecoder(r.Body).Decode(&resp) + err := httputil.DecodeJSONResponse(r, &resp) return resp, err } diff --git a/platform/blueprint/client.go b/platform/blueprint/client.go index 051577cc..16b84a8f 100644 --- a/platform/blueprint/client.go +++ b/platform/blueprint/client.go @@ -1,13 +1,12 @@ package blueprint import ( - "context" - "net/http" "net/url" "github.com/go-kit/kit/endpoint" "github.com/go-kit/kit/log" httptransport "github.com/go-kit/kit/transport/http" + "github.com/micromdm/micromdm/pkg/httputil" ) func NewHTTPClient(instance, token string, logger log.Logger, opts ...httptransport.ClientOption) (Service, error) { @@ -20,8 +19,8 @@ func NewHTTPClient(instance, token string, logger log.Logger, opts ...httptransp { applyBlueprintEndpoint = httptransport.NewClient( "PUT", - copyURL(u, "/v1/blueprints"), - encodeRequestWithToken(token, httptransport.EncodeJSONRequest), + httputil.CopyURL(u, "/v1/blueprints"), + httputil.EncodeRequestWithToken(token, httptransport.EncodeJSONRequest), decodeApplyBlueprintResponse, opts..., ).Endpoint() @@ -31,8 +30,8 @@ func NewHTTPClient(instance, token string, logger log.Logger, opts ...httptransp { getBlueprintsEndpoint = httptransport.NewClient( "GET", - copyURL(u, "/v1/blueprints"), - encodeRequestWithToken(token, httptransport.EncodeJSONRequest), + httputil.CopyURL(u, "/v1/blueprints"), + httputil.EncodeRequestWithToken(token, httptransport.EncodeJSONRequest), decodeGetBlueprintsResponse, opts..., ).Endpoint() @@ -42,8 +41,8 @@ func NewHTTPClient(instance, token string, logger log.Logger, opts ...httptransp { removeBlueprintsEndpoint = httptransport.NewClient( "DELETE", - copyURL(u, "/v1/blueprints"), - encodeRequestWithToken(token, httptransport.EncodeJSONRequest), + httputil.CopyURL(u, "/v1/blueprints"), + httputil.EncodeRequestWithToken(token, httptransport.EncodeJSONRequest), decodeRemoveBlueprintsResponse, opts..., ).Endpoint() @@ -55,16 +54,3 @@ func NewHTTPClient(instance, token string, logger log.Logger, opts ...httptransp RemoveBlueprintsEndpoint: removeBlueprintsEndpoint, }, nil } - -func encodeRequestWithToken(token string, next httptransport.EncodeRequestFunc) httptransport.EncodeRequestFunc { - return func(ctx context.Context, r *http.Request, request interface{}) error { - r.SetBasicAuth("micromdm", token) - return next(ctx, r, request) - } -} - -func copyURL(base *url.URL, path string) *url.URL { - next := *base - next.Path = path - return &next -} diff --git a/platform/blueprint/get_bplueprints.go b/platform/blueprint/get_bplueprints.go index f70702fd..ea34bca1 100644 --- a/platform/blueprint/get_bplueprints.go +++ b/platform/blueprint/get_bplueprints.go @@ -6,6 +6,7 @@ import ( "net/http" "github.com/go-kit/kit/endpoint" + "github.com/micromdm/micromdm/pkg/httputil" ) func (svc *BlueprintService) GetBlueprints(ctx context.Context, opt GetBlueprintsOption) ([]Blueprint, error) { @@ -30,7 +31,7 @@ type getBlueprintsResponse struct { Err error `json:"err,omitempty"` } -func (r getBlueprintsResponse) error() error { return r.Err } +func (r getBlueprintsResponse) Failed() error { return r.Err } func decodeGetBlueprintsRequest(ctx context.Context, r *http.Request) (interface{}, error) { var opts GetBlueprintsOption @@ -44,11 +45,8 @@ func decodeGetBlueprintsRequest(ctx context.Context, r *http.Request) (interface } func decodeGetBlueprintsResponse(_ context.Context, r *http.Response) (interface{}, error) { - if r.StatusCode != http.StatusOK { - return nil, errorDecoder(r) - } var resp getBlueprintsResponse - err := json.NewDecoder(r.Body).Decode(&resp) + err := httputil.DecodeJSONResponse(r, &resp) return resp, err } diff --git a/platform/blueprint/remove_blueprints.go b/platform/blueprint/remove_blueprints.go index d7f9c55d..622527c8 100644 --- a/platform/blueprint/remove_blueprints.go +++ b/platform/blueprint/remove_blueprints.go @@ -2,10 +2,10 @@ package blueprint import ( "context" - "encoding/json" "net/http" "github.com/go-kit/kit/endpoint" + "github.com/micromdm/micromdm/pkg/httputil" ) func (svc *BlueprintService) RemoveBlueprints(ctx context.Context, names []string) error { @@ -26,22 +26,17 @@ type removeBlueprintsResponse struct { Err error `json:"err,omitempty"` } -func (r removeBlueprintsResponse) error() error { return r.Err } +func (r removeBlueprintsResponse) Failed() error { return r.Err } func decodeRemoveBlueprintsRequest(ctx context.Context, r *http.Request) (interface{}, error) { var req removeBlueprintsRequest - if err := json.NewDecoder(r.Body).Decode(&req); err != nil { - return nil, err - } - return req, nil + err := httputil.DecodeJSONRequest(r, &req) + return req, err } func decodeRemoveBlueprintsResponse(_ context.Context, r *http.Response) (interface{}, error) { - if r.StatusCode != http.StatusOK { - return nil, errorDecoder(r) - } var resp removeBlueprintsResponse - err := json.NewDecoder(r.Body).Decode(&resp) + err := httputil.DecodeJSONResponse(r, &resp) return resp, err } diff --git a/platform/blueprint/server.go b/platform/blueprint/server.go index 0248f4cd..563923c9 100644 --- a/platform/blueprint/server.go +++ b/platform/blueprint/server.go @@ -1,14 +1,12 @@ package blueprint import ( - "encoding/json" "net/http" "github.com/go-kit/kit/endpoint" "github.com/go-kit/kit/log" httptransport "github.com/go-kit/kit/transport/http" - "github.com/gorilla/mux" - "github.com/pkg/errors" + "github.com/micromdm/micromdm/pkg/httputil" ) type Endpoints struct { @@ -19,17 +17,14 @@ type Endpoints struct { func MakeServerEndpoints(s Service) Endpoints { return Endpoints{ - GetBlueprintsEndpoint: MakeGetBlueprintsEndpoint(s), - ApplyBlueprintEndpoint: MakeApplyBlueprintEndpoint(s), + GetBlueprintsEndpoint: MakeGetBlueprintsEndpoint(s), + ApplyBlueprintEndpoint: MakeApplyBlueprintEndpoint(s), + RemoveBlueprintsEndpoint: MakeRemoveBlueprintsEndpoint(s), } } func MakeHTTPHandler(e Endpoints, logger log.Logger) http.Handler { - options := []httptransport.ServerOption{ - httptransport.ServerErrorLogger(logger), - } - - r := mux.NewRouter() + r, options := httputil.NewRouter(logger) // PUT /v1/blueprints create or replace a blueprint on the server // GET /v1/blueprints get a list of blueprints managed by the server @@ -38,39 +33,23 @@ func MakeHTTPHandler(e Endpoints, logger log.Logger) http.Handler { r.Methods("PUT").Path("/v1/blueprints").Handler(httptransport.NewServer( e.ApplyBlueprintEndpoint, decodeApplyBlueprintRequest, - httptransport.EncodeJSONResponse, + httputil.EncodeJSONResponse, options..., )) r.Methods("GET").Path("/v1/blueprints").Handler(httptransport.NewServer( e.GetBlueprintsEndpoint, decodeGetBlueprintsRequest, - httptransport.EncodeJSONResponse, + httputil.EncodeJSONResponse, options..., )) r.Methods("DELETE").Path("/v1/blueprints").Handler(httptransport.NewServer( e.RemoveBlueprintsEndpoint, decodeRemoveBlueprintsRequest, - httptransport.EncodeJSONResponse, + httputil.EncodeJSONResponse, options..., )) return r } - -type errorWrapper struct { - Error string `json:"error"` -} - -type errorer interface { - error() error -} - -func errorDecoder(r *http.Response) error { - var w errorWrapper - if err := json.NewDecoder(r.Body).Decode(&w); err != nil { - return err - } - return errors.New(w.Error) -} diff --git a/platform/profile/apply_profile.go b/platform/profile/apply_profile.go index cf3b5a6c..aacb03ce 100644 --- a/platform/profile/apply_profile.go +++ b/platform/profile/apply_profile.go @@ -2,10 +2,10 @@ package profile import ( "context" - "encoding/json" "net/http" "github.com/go-kit/kit/endpoint" + "github.com/micromdm/micromdm/pkg/httputil" ) func (svc *ProfileService) ApplyProfile(ctx context.Context, p *Profile) error { @@ -20,22 +20,17 @@ type applyProfileResponse struct { Err error `json:"err,omitempty"` } -func (r applyProfileResponse) error() error { return r.Err } +func (r applyProfileResponse) Failed() error { return r.Err } func decodeApplyProfileRequest(ctx context.Context, r *http.Request) (interface{}, error) { var req applyProfileRequest - if err := json.NewDecoder(r.Body).Decode(&req); err != nil { - return nil, err - } - return req, nil + err := httputil.DecodeJSONRequest(r, &req) + return req, err } func decodeApplyProfileResponse(_ context.Context, r *http.Response) (interface{}, error) { - if r.StatusCode != http.StatusOK { - return nil, errorDecoder(r) - } var resp applyProfileResponse - err := json.NewDecoder(r.Body).Decode(&resp) + err := httputil.DecodeJSONResponse(r, &resp) return resp, err } diff --git a/platform/profile/client.go b/platform/profile/client.go index 938a2437..4e933c30 100644 --- a/platform/profile/client.go +++ b/platform/profile/client.go @@ -1,13 +1,12 @@ package profile import ( - "context" - "net/http" "net/url" "github.com/go-kit/kit/endpoint" "github.com/go-kit/kit/log" httptransport "github.com/go-kit/kit/transport/http" + "github.com/micromdm/micromdm/pkg/httputil" ) func NewHTTPClient(instance, token string, logger log.Logger, opts ...httptransport.ClientOption) (Service, error) { @@ -20,8 +19,8 @@ func NewHTTPClient(instance, token string, logger log.Logger, opts ...httptransp { applyProfileEndpoint = httptransport.NewClient( "PUT", - copyURL(u, "/v1/profiles"), - encodeRequestWithToken(token, httptransport.EncodeJSONRequest), + httputil.CopyURL(u, "/v1/profiles"), + httputil.EncodeRequestWithToken(token, httptransport.EncodeJSONRequest), decodeApplyProfileResponse, opts..., ).Endpoint() @@ -31,8 +30,8 @@ func NewHTTPClient(instance, token string, logger log.Logger, opts ...httptransp { getProfilesEndpoint = httptransport.NewClient( "GET", - copyURL(u, "/v1/profiles"), - encodeRequestWithToken(token, httptransport.EncodeJSONRequest), + httputil.CopyURL(u, "/v1/profiles"), + httputil.EncodeRequestWithToken(token, httptransport.EncodeJSONRequest), decodeGetProfilesResponse, opts..., ).Endpoint() @@ -42,8 +41,8 @@ func NewHTTPClient(instance, token string, logger log.Logger, opts ...httptransp { removeProfilesEndpoint = httptransport.NewClient( "DELETE", - copyURL(u, "/v1/profiles"), - encodeRequestWithToken(token, httptransport.EncodeJSONRequest), + httputil.CopyURL(u, "/v1/profiles"), + httputil.EncodeRequestWithToken(token, httptransport.EncodeJSONRequest), decodeRemoveProfileResponse, opts..., ).Endpoint() @@ -55,16 +54,3 @@ func NewHTTPClient(instance, token string, logger log.Logger, opts ...httptransp RemoveProfilesEndpoint: removeProfilesEndpoint, }, nil } - -func encodeRequestWithToken(token string, next httptransport.EncodeRequestFunc) httptransport.EncodeRequestFunc { - return func(ctx context.Context, r *http.Request, request interface{}) error { - r.SetBasicAuth("micromdm", token) - return next(ctx, r, request) - } -} - -func copyURL(base *url.URL, path string) *url.URL { - next := *base - next.Path = path - return &next -} diff --git a/platform/profile/get_profiles.go b/platform/profile/get_profiles.go index 3d84cc94..158f84f8 100644 --- a/platform/profile/get_profiles.go +++ b/platform/profile/get_profiles.go @@ -6,6 +6,7 @@ import ( "net/http" "github.com/go-kit/kit/endpoint" + "github.com/micromdm/micromdm/pkg/httputil" ) func (svc *ProfileService) GetProfiles(ctx context.Context, opt GetProfilesOption) ([]Profile, error) { @@ -27,7 +28,7 @@ type getProfilesResponse struct { Err error `json:"err,omitempty"` } -func (r getProfilesResponse) error() error { return r.Err } +func (r getProfilesResponse) Failed() error { return r.Err } func decodeGetProfilesRequest(ctx context.Context, r *http.Request) (interface{}, error) { var opts GetProfilesOption @@ -41,11 +42,8 @@ func decodeGetProfilesRequest(ctx context.Context, r *http.Request) (interface{} } func decodeGetProfilesResponse(_ context.Context, r *http.Response) (interface{}, error) { - if r.StatusCode != http.StatusOK { - return nil, errorDecoder(r) - } var resp getProfilesResponse - err := json.NewDecoder(r.Body).Decode(&resp) + err := httputil.DecodeJSONResponse(r, &resp) return resp, err } diff --git a/platform/profile/remove_profiles.go b/platform/profile/remove_profiles.go index 5677d88a..86189156 100644 --- a/platform/profile/remove_profiles.go +++ b/platform/profile/remove_profiles.go @@ -2,10 +2,10 @@ package profile import ( "context" - "encoding/json" "net/http" "github.com/go-kit/kit/endpoint" + "github.com/micromdm/micromdm/pkg/httputil" ) func (svc *ProfileService) RemoveProfiles(ctx context.Context, ids []string) error { @@ -26,22 +26,17 @@ type removeProfileResponse struct { Err error `json:"err,omitempty"` } -func (r removeProfileResponse) error() error { return r.Err } +func (r removeProfileResponse) Failed() error { return r.Err } func decodeRemoveProfilesRequest(ctx context.Context, r *http.Request) (interface{}, error) { var req removeProfileRequest - if err := json.NewDecoder(r.Body).Decode(&req); err != nil { - return nil, err - } - return req, nil + err := httputil.DecodeJSONRequest(r, &req) + return req, err } func decodeRemoveProfileResponse(_ context.Context, r *http.Response) (interface{}, error) { - if r.StatusCode != http.StatusOK { - return nil, errorDecoder(r) - } var resp removeProfileResponse - err := json.NewDecoder(r.Body).Decode(&resp) + err := httputil.DecodeJSONResponse(r, &resp) return resp, err } diff --git a/platform/profile/server.go b/platform/profile/server.go index 2abd6ec0..8e0e5615 100644 --- a/platform/profile/server.go +++ b/platform/profile/server.go @@ -1,14 +1,12 @@ package profile import ( - "encoding/json" - "errors" "net/http" "github.com/go-kit/kit/endpoint" "github.com/go-kit/kit/log" httptransport "github.com/go-kit/kit/transport/http" - "github.com/gorilla/mux" + "github.com/micromdm/micromdm/pkg/httputil" ) type Endpoints struct { @@ -26,11 +24,7 @@ func MakeServerEndpoints(s Service) Endpoints { } func MakeHTTPHandler(e Endpoints, logger log.Logger) http.Handler { - options := []httptransport.ServerOption{ - httptransport.ServerErrorLogger(logger), - } - - r := mux.NewRouter() + r, options := httputil.NewRouter(logger) // GET /v1/profiles get a list of profiles managed by the server // PUT /v1/profiles create or replace a profile on the server @@ -39,39 +33,23 @@ func MakeHTTPHandler(e Endpoints, logger log.Logger) http.Handler { r.Methods("GET").Path("/v1/profiles").Handler(httptransport.NewServer( e.GetProfilesEndpoint, decodeGetProfilesRequest, - httptransport.EncodeJSONResponse, + httputil.EncodeJSONResponse, options..., )) r.Methods("PUT").Path("/v1/profiles").Handler(httptransport.NewServer( e.ApplyProfileEndpoint, decodeApplyProfileRequest, - httptransport.EncodeJSONResponse, + httputil.EncodeJSONResponse, options..., )) r.Methods("DELETE").Path("/v1/profiles").Handler(httptransport.NewServer( e.RemoveProfilesEndpoint, decodeRemoveProfilesRequest, - httptransport.EncodeJSONResponse, + httputil.EncodeJSONResponse, options..., )) return r } - -type errorWrapper struct { - Error string `json:"error"` -} - -type errorer interface { - error() error -} - -func errorDecoder(r *http.Response) error { - var w errorWrapper - if err := json.NewDecoder(r.Body).Decode(&w); err != nil { - return err - } - return errors.New(w.Error) -} diff --git a/platform/remove/block_device.go b/platform/remove/block_device.go index d103995d..a108f644 100644 --- a/platform/remove/block_device.go +++ b/platform/remove/block_device.go @@ -2,12 +2,12 @@ package remove import ( "context" - "encoding/json" "net/http" "net/url" "github.com/go-kit/kit/endpoint" "github.com/gorilla/mux" + "github.com/micromdm/micromdm/pkg/httputil" "github.com/pkg/errors" ) @@ -23,7 +23,7 @@ type blockDeviceResponse struct { Err error `json:"err,omitempty"` } -func (r blockDeviceResponse) error() error { return r.Err } +func (r blockDeviceResponse) Failed() error { return r.Err } func decodeBlockDeviceRequest(ctx context.Context, r *http.Request) (interface{}, error) { var errBadRoute = errors.New("bad route") @@ -45,11 +45,8 @@ func encodeBlockDeviceRequest(_ context.Context, r *http.Request, request interf } func decodeBlockDeviceResponse(_ context.Context, r *http.Response) (interface{}, error) { - if r.StatusCode != http.StatusOK { - return nil, errorDecoder(r) - } var resp blockDeviceResponse - err := json.NewDecoder(r.Body).Decode(&resp) + err := httputil.DecodeJSONResponse(r, &resp) return resp, err } diff --git a/platform/remove/client.go b/platform/remove/client.go index cc5cd46f..182a7f4b 100644 --- a/platform/remove/client.go +++ b/platform/remove/client.go @@ -1,13 +1,12 @@ package remove import ( - "context" - "net/http" "net/url" "github.com/go-kit/kit/endpoint" "github.com/go-kit/kit/log" httptransport "github.com/go-kit/kit/transport/http" + "github.com/micromdm/micromdm/pkg/httputil" ) func NewHTTPClient(instance, token string, logger log.Logger, opts ...httptransport.ClientOption) (Service, error) { @@ -20,8 +19,8 @@ func NewHTTPClient(instance, token string, logger log.Logger, opts ...httptransp { blockDeviceEndpoint = httptransport.NewClient( "POST", - copyURL(u, ""), // empty path, modified by the encodeRequest func - encodeRequestWithToken(token, encodeBlockDeviceRequest), + httputil.CopyURL(u, ""), // empty path, modified by the encodeRequest func + httputil.EncodeRequestWithToken(token, encodeBlockDeviceRequest), decodeBlockDeviceResponse, opts..., ).Endpoint() @@ -31,8 +30,8 @@ func NewHTTPClient(instance, token string, logger log.Logger, opts ...httptransp { unblockDeviceEndpoint = httptransport.NewClient( "POST", - copyURL(u, ""), //modified by encodeRequestFunc - encodeRequestWithToken(token, encodeUnblockDeviceRequest), + httputil.CopyURL(u, ""), //modified by encodeRequestFunc + httputil.EncodeRequestWithToken(token, encodeUnblockDeviceRequest), decodeUnblockDeviceResponse, opts..., ).Endpoint() @@ -43,16 +42,3 @@ func NewHTTPClient(instance, token string, logger log.Logger, opts ...httptransp UnblockDeviceEndpoint: unblockDeviceEndpoint, }, nil } - -func encodeRequestWithToken(token string, next httptransport.EncodeRequestFunc) httptransport.EncodeRequestFunc { - return func(ctx context.Context, r *http.Request, request interface{}) error { - r.SetBasicAuth("micromdm", token) - return next(ctx, r, request) - } -} - -func copyURL(base *url.URL, path string) *url.URL { - next := *base - next.Path = path - return &next -} diff --git a/platform/remove/server.go b/platform/remove/server.go index 4bb82ef4..7d8f6c30 100644 --- a/platform/remove/server.go +++ b/platform/remove/server.go @@ -1,14 +1,12 @@ package remove import ( - "encoding/json" - "errors" "net/http" "github.com/go-kit/kit/endpoint" "github.com/go-kit/kit/log" httptransport "github.com/go-kit/kit/transport/http" - "github.com/gorilla/mux" + "github.com/micromdm/micromdm/pkg/httputil" ) type Endpoints struct { @@ -24,11 +22,7 @@ func MakeServerEndpoints(s Service) Endpoints { } func MakeHTTPHandler(e Endpoints, logger log.Logger) http.Handler { - options := []httptransport.ServerOption{ - httptransport.ServerErrorLogger(logger), - } - - r := mux.NewRouter() + r, options := httputil.NewRouter(logger) // POST /v1/devices/:udid/block force a device to unenroll next time it connects // POST /v1/devices/:udid/unblock allow a blocked device to enroll again @@ -36,33 +30,17 @@ func MakeHTTPHandler(e Endpoints, logger log.Logger) http.Handler { r.Methods("POST").Path("/v1/devices/{udid}/block").Handler(httptransport.NewServer( e.BlockDeviceEndpoint, decodeBlockDeviceRequest, - httptransport.EncodeJSONResponse, + httputil.EncodeJSONResponse, options..., )) r.Methods("POST").Path("/v1/devices/{udid}/unblock").Handler(httptransport.NewServer( e.UnblockDeviceEndpoint, decodeUnblockDeviceRequest, - httptransport.EncodeJSONResponse, + httputil.EncodeJSONResponse, options..., )) return r } - -type errorWrapper struct { - Error string `json:"error"` -} - -type errorer interface { - error() error -} - -func errorDecoder(r *http.Response) error { - var w errorWrapper - if err := json.NewDecoder(r.Body).Decode(&w); err != nil { - return err - } - return errors.New(w.Error) -} diff --git a/platform/remove/unblock_device.go b/platform/remove/unblock_device.go index 73b53135..78ce069e 100644 --- a/platform/remove/unblock_device.go +++ b/platform/remove/unblock_device.go @@ -2,13 +2,13 @@ package remove import ( "context" - "encoding/json" "errors" "net/http" "net/url" "github.com/go-kit/kit/endpoint" "github.com/gorilla/mux" + "github.com/micromdm/micromdm/pkg/httputil" ) func (svc *RemoveService) UnblockDevice(ctx context.Context, udid string) error { @@ -23,7 +23,7 @@ type unblockDeviceResponse struct { Err error `json:"err,omitempty"` } -func (r unblockDeviceResponse) error() error { return r.Err } +func (r unblockDeviceResponse) Failed() error { return r.Err } func decodeUnblockDeviceRequest(ctx context.Context, r *http.Request) (interface{}, error) { var errBadRoute = errors.New("bad route") @@ -45,11 +45,8 @@ func encodeUnblockDeviceRequest(_ context.Context, r *http.Request, request inte } func decodeUnblockDeviceResponse(_ context.Context, r *http.Response) (interface{}, error) { - if r.StatusCode != http.StatusOK { - return nil, errorDecoder(r) - } var resp unblockDeviceResponse - err := json.NewDecoder(r.Body).Decode(&resp) + err := httputil.DecodeJSONResponse(r, &resp) return resp, err }