Files
micromdm/command/transport.go
mosen bd5d996d73 Commands management plus fixes (#20)
* Add commands index to command datastore.
Add simple test for commands index
Add commands index endpoint

(cherry picked from commit 4e2a2a2)

* Add handler for GET /mdm/commands

(cherry picked from commit ae71b8f)

* Added Find() method to commands datastore so that the request that matches a response can be retrieved by the connect service.
Added Find() method to command service

(cherry picked from commit ebceb28)

* Fix globally scoped vars in command datastore test suite

* groob prefers inline definition of struct members.

* Uppercase CommandUuid
2016-10-07 11:17:47 +11:00

159 lines
3.7 KiB
Go

package command
import (
"encoding/json"
"net/http"
kitlog "github.com/go-kit/kit/log"
kithttp "github.com/go-kit/kit/transport/http"
"github.com/gorilla/mux"
"golang.org/x/net/context"
)
// ServiceHandler returns an HTTP Handler for the command service
func ServiceHandler(ctx context.Context, svc Service, logger kitlog.Logger) http.Handler {
opts := []kithttp.ServerOption{
kithttp.ServerErrorLogger(logger),
kithttp.ServerErrorEncoder(encodeError),
}
newCommandHandler := kithttp.NewServer(
ctx,
makeNewCommandEndpoint(svc),
decodeNewCommandRequest,
encodeResponse,
opts...,
)
nextCommandHandler := kithttp.NewServer(
ctx,
makeNextCommandEndpoint(svc),
decodeNextCommandRequest,
encodeResponse,
opts...,
)
deleteCommandHandler := kithttp.NewServer(
ctx,
makeDeleteCommandEndpoint(svc),
decodeDeleteCommandRequest,
encodeResponse,
opts...,
)
getCommandsHandler := kithttp.NewServer(
ctx,
makeGetCommandsEndpoint(svc),
decodeGetCommandsRequest,
encodeResponse,
opts...,
)
r := mux.NewRouter()
r.Handle("/mdm/commands/{udid}", getCommandsHandler).Methods("GET")
r.Handle("/mdm/commands", newCommandHandler).Methods("POST")
r.Handle("/mdm/commands/{udid}/next", nextCommandHandler).Methods("GET")
r.Handle("/mdm/commands/{udid}/{uuid}", deleteCommandHandler).Methods("DELETE")
return r
}
func decodeNewCommandRequest(_ context.Context, r *http.Request) (interface{}, error) {
var request newCommandRequest
err := json.NewDecoder(r.Body).Decode(&request.CommandRequest)
return request, err
}
func decodeNextCommandRequest(_ context.Context, r *http.Request) (interface{}, error) {
vars := mux.Vars(r)
udid, ok := vars["udid"]
if !ok {
return nil, errBadRouting
}
var request nextCommandRequest
request.UDID = udid
return request, nil
}
func decodeDeleteCommandRequest(_ context.Context, r *http.Request) (interface{}, error) {
vars := mux.Vars(r)
udid, ok := vars["udid"]
if !ok {
return nil, errBadRouting
}
uuid, ok := vars["uuid"]
if !ok {
return nil, errBadRouting
}
var request deleteCommandRequest
request.UDID = udid
request.UUID = uuid
return request, nil
}
func decodeGetCommandsRequest(_ context.Context, r *http.Request) (interface{}, error) {
vars := mux.Vars(r)
udid, ok := vars["udid"]
if !ok {
return nil, errBadRouting
}
request := getCommandsRequest{UDID: udid}
return request, nil
}
type errorer interface {
error() error
}
type statuser interface {
status() int
}
type listEncoder interface {
encodeList(w http.ResponseWriter) error
}
func encodeResponse(ctx context.Context, w http.ResponseWriter, response interface{}) error {
if e, ok := response.(errorer); ok && e.error() != nil {
encodeError(ctx, e.error(), w)
return nil
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
// for success responses
if e, ok := response.(statuser); ok {
w.WriteHeader(e.status())
if e.status() == http.StatusNoContent {
return nil
}
}
// check if this is a collection
if e, ok := response.(listEncoder); ok {
return e.encodeList(w)
}
return json.NewEncoder(w).Encode(response)
}
// encode errors from business-logic
func encodeError(_ context.Context, err error, w http.ResponseWriter) {
// unwrap if the error is wrapped by kit http in it's own error type
if httperr, ok := err.(kithttp.Error); ok {
err = httperr.Err
}
switch err {
// case ErrNotFound:
// w.WriteHeader(http.StatusNotFound)
// case errEmptyRequest, errBadUUID:
// w.WriteHeader(http.StatusBadRequest)
// case workflow.ErrExists:
// w.WriteHeader(http.StatusConflict)
default:
w.WriteHeader(http.StatusInternalServerError)
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
json.NewEncoder(w).Encode(map[string]interface{}{
"error": err.Error(),
})
}