From 5dd554dbc6f1893b09cef37566f216ab5f8beb3b Mon Sep 17 00:00:00 2001 From: Adrian Zankich Date: Sun, 7 Dec 2014 08:54:50 -0800 Subject: [PATCH] Add more error handling for unknown robots, devices and connections --- api/api.go | 160 +++++++++++++++++++++++++++++++++--------------- api/api_test.go | 6 +- 2 files changed, 114 insertions(+), 52 deletions(-) diff --git a/api/api.go b/api/api.go index 94b8854b..31d42e12 100644 --- a/api/api.go +++ b/api/api.go @@ -2,6 +2,7 @@ package api import ( "encoding/json" + "errors" "fmt" "log" "net/http" @@ -182,32 +183,45 @@ func (a *api) robots(res http.ResponseWriter, req *http.Request) { // robot returns route handler. // Writes JSON with robot representation func (a *api) robot(res http.ResponseWriter, req *http.Request) { - a.writeJSON(map[string]interface{}{"robot": gobot.NewJSONRobot(a.gobot.Robot(req.URL.Query().Get(":robot")))}, res) + if robot, err := a.jsonRobotFor(req.URL.Query().Get(":robot")); err != nil { + a.writeJSON(map[string]interface{}{"error": err.Error()}, res) + } else { + a.writeJSON(map[string]interface{}{"robot": robot}, res) + } } // robotCommands returns commands route handler // Writes JSON with robot commands representation func (a *api) robotCommands(res http.ResponseWriter, req *http.Request) { - a.writeJSON(map[string]interface{}{"commands": gobot.NewJSONRobot(a.gobot.Robot(req.URL.Query().Get(":robot"))).Commands}, res) + if robot, err := a.jsonRobotFor(req.URL.Query().Get(":robot")); err != nil { + a.writeJSON(map[string]interface{}{"error": err.Error()}, res) + } else { + a.writeJSON(map[string]interface{}{"commands": robot.Commands}, res) + } } // robotDevices returns devices route handler. // Writes JSON with robot devices representation func (a *api) robotDevices(res http.ResponseWriter, req *http.Request) { - jsonDevices := []*gobot.JSONDevice{} - a.gobot.Robot(req.URL.Query().Get(":robot")).Devices().Each(func(d gobot.Device) { - jsonDevices = append(jsonDevices, gobot.NewJSONDevice(d)) - }) - a.writeJSON(map[string]interface{}{"devices": jsonDevices}, res) + if robot := a.gobot.Robot(req.URL.Query().Get(":robot")); robot != nil { + jsonDevices := []*gobot.JSONDevice{} + robot.Devices().Each(func(d gobot.Device) { + jsonDevices = append(jsonDevices, gobot.NewJSONDevice(d)) + }) + a.writeJSON(map[string]interface{}{"devices": jsonDevices}, res) + } else { + a.writeJSON(map[string]interface{}{"error": "No Robot found with the name " + req.URL.Query().Get(":robot")}, res) + } } // robotDevice returns device route handler. // Writes JSON with robot device representation func (a *api) robotDevice(res http.ResponseWriter, req *http.Request) { - a.writeJSON( - map[string]interface{}{"device": gobot.NewJSONDevice(a.gobot.Robot(req.URL.Query().Get(":robot")). - Device(req.URL.Query().Get(":device")))}, res, - ) + if device, err := a.jsonDeviceFor(req.URL.Query().Get(":robot"), req.URL.Query().Get(":device")); err != nil { + a.writeJSON(map[string]interface{}{"error": err.Error()}, res) + } else { + a.writeJSON(map[string]interface{}{"device": device}, res) + } } // robotDeviceEvent returns device event route handler. @@ -224,52 +238,64 @@ func (a *api) robotDeviceEvent(res http.ResponseWriter, req *http.Request) { res.Header().Set("Cache-Control", "no-cache") res.Header().Set("Connection", "keep-alive") - gobot.On(a.gobot.Robot(req.URL.Query().Get(":robot")). - Device(req.URL.Query().Get(":device")).(gobot.Eventer).Event(req.URL.Query().Get(":event")), - func(data interface{}) { + if event := a.gobot.Robot(req.URL.Query().Get(":robot")). + Device(req.URL.Query().Get(":device")).(gobot.Eventer). + Event(req.URL.Query().Get(":event")); event != nil { + gobot.On(event, func(data interface{}) { d, _ := json.Marshal(data) msg <- string(d) }) - for { - select { - case data := <-msg: - fmt.Fprintf(res, "data: %v\n\n", data) - f.Flush() - case <-closer: - log.Println("Closing connection") - return + for { + select { + case data := <-msg: + fmt.Fprintf(res, "data: %v\n\n", data) + f.Flush() + case <-closer: + log.Println("Closing connection") + return + } } + } else { + a.writeJSON(map[string]interface{}{ + "error": errors.New("No Event found with the name " + req.URL.Query().Get(":event")), + }, res) } } // robotDeviceCommands returns device commands route handler // writes JSON with robot device commands representation func (a *api) robotDeviceCommands(res http.ResponseWriter, req *http.Request) { - a.writeJSON( - map[string]interface{}{"commands": gobot.NewJSONDevice(a.gobot.Robot(req.URL.Query().Get(":robot")). - Device(req.URL.Query().Get(":device"))).Commands}, res, - ) + if device, err := a.jsonDeviceFor(req.URL.Query().Get(":robot"), req.URL.Query().Get(":device")); err != nil { + a.writeJSON(map[string]interface{}{"error": err.Error()}, res) + } else { + a.writeJSON(map[string]interface{}{"commands": device.Commands}, res) + } } // robotConnections returns connections route handler // writes JSON with robot connections representation func (a *api) robotConnections(res http.ResponseWriter, req *http.Request) { jsonConnections := []*gobot.JSONConnection{} - a.gobot.Robot(req.URL.Query().Get(":robot")).Connections().Each(func(c gobot.Connection) { - jsonConnections = append(jsonConnections, gobot.NewJSONConnection(c)) - }) - a.writeJSON(map[string]interface{}{"connections": jsonConnections}, res) + if robot := a.gobot.Robot(req.URL.Query().Get(":robot")); robot != nil { + robot.Connections().Each(func(c gobot.Connection) { + jsonConnections = append(jsonConnections, gobot.NewJSONConnection(c)) + }) + a.writeJSON(map[string]interface{}{"connections": jsonConnections}, res) + } else { + a.writeJSON(map[string]interface{}{"error": "No Robot found with the name " + req.URL.Query().Get(":robot")}, res) + } + } // robotConnection returns connection route handler // writes JSON with robot connection representation func (a *api) robotConnection(res http.ResponseWriter, req *http.Request) { - a.writeJSON( - map[string]interface{}{"connection": gobot.NewJSONConnection(a.gobot.Robot(req.URL.Query().Get(":robot")). - Connection(req.URL.Query().Get(":connection")))}, - res, - ) + if conn, err := a.jsonConnectionFor(req.URL.Query().Get(":robot"), req.URL.Query().Get(":connection")); err != nil { + a.writeJSON(map[string]interface{}{"error": err.Error()}, res) + } else { + a.writeJSON(map[string]interface{}{"connection": conn}, res) + } } // executeMcpCommand calls a global command asociated to requested route @@ -282,23 +308,32 @@ func (a *api) executeMcpCommand(res http.ResponseWriter, req *http.Request) { // executeDeviceCommand calls a device command asociated to requested route func (a *api) executeDeviceCommand(res http.ResponseWriter, req *http.Request) { - a.executeCommand( - a.gobot.Robot(req.URL.Query().Get(":robot")). - Device(req.URL.Query().Get(":device")).(gobot.Commander). - Command(req.URL.Query().Get(":command")), - res, - req, - ) + if _, err := a.jsonDeviceFor(req.URL.Query().Get(":robot"), + req.URL.Query().Get(":device")); err != nil { + a.writeJSON(map[string]interface{}{"error": err.Error()}, res) + } else { + a.executeCommand( + a.gobot.Robot(req.URL.Query().Get(":robot")). + Device(req.URL.Query().Get(":device")).(gobot.Commander). + Command(req.URL.Query().Get(":command")), + res, + req, + ) + } } // executeRobotCommand calls a robot command asociated to requested route func (a *api) executeRobotCommand(res http.ResponseWriter, req *http.Request) { - a.executeCommand( - a.gobot.Robot(req.URL.Query().Get(":robot")). - Command(req.URL.Query().Get(":command")), - res, - req, - ) + if _, err := a.jsonRobotFor(req.URL.Query().Get(":robot")); err != nil { + a.writeJSON(map[string]interface{}{"error": err.Error()}, res) + } else { + a.executeCommand( + a.gobot.Robot(req.URL.Query().Get(":robot")). + Command(req.URL.Query().Get(":command")), + res, + req, + ) + } } // executeCommand writes JSON response with `f` returned value. @@ -313,7 +348,7 @@ func (a *api) executeCommand(f func(map[string]interface{}) interface{}, if f != nil { a.writeJSON(map[string]interface{}{"result": f(body)}, res) } else { - a.writeJSON("Unknown Command", res) + a.writeJSON(map[string]interface{}{"error": "Unknown Command"}, res) } } @@ -330,3 +365,30 @@ func (a *api) Debug() { log.Println(req) }) } + +func (a *api) jsonRobotFor(name string) (jrobot *gobot.JSONRobot, err error) { + if robot := a.gobot.Robot(name); robot != nil { + jrobot = gobot.NewJSONRobot(robot) + } else { + err = errors.New("No Robot found with the name " + name) + } + return +} + +func (a *api) jsonDeviceFor(robot string, name string) (jdevice *gobot.JSONDevice, err error) { + if device := a.gobot.Robot(robot).Device(name); device != nil { + jdevice = gobot.NewJSONDevice(device) + } else { + err = errors.New("No Device found with the name " + name) + } + return +} + +func (a *api) jsonConnectionFor(robot string, name string) (jconnection *gobot.JSONConnection, err error) { + if connection := a.gobot.Robot(robot).Connection(name); connection != nil { + jconnection = gobot.NewJSONConnection(connection) + } else { + err = errors.New("No Connection found with the name " + name) + } + return +} diff --git a/api/api_test.go b/api/api_test.go index 25f35c77..ee4f15a5 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -104,7 +104,7 @@ func TestExecuteMcpCommand(t *testing.T) { a.ServeHTTP(response, request) json.NewDecoder(response.Body).Decode(&body) - gobot.Assert(t, body, "Unknown Command") + gobot.Assert(t, body.(map[string]interface{})["error"], "Unknown Command") } func TestRobots(t *testing.T) { @@ -176,7 +176,7 @@ func TestExecuteRobotCommand(t *testing.T) { a.ServeHTTP(response, request) json.NewDecoder(response.Body).Decode(&body) - gobot.Assert(t, body, "Unknown Command") + gobot.Assert(t, body.(map[string]interface{})["error"], "Unknown Command") } func TestRobotDevice(t *testing.T) { @@ -233,7 +233,7 @@ func TestExecuteRobotDeviceCommand(t *testing.T) { a.ServeHTTP(response, request) json.NewDecoder(response.Body).Decode(&body) - gobot.Assert(t, body, "Unknown Command") + gobot.Assert(t, body.(map[string]interface{})["error"], "Unknown Command") } func TestRobotConnections(t *testing.T) {