diff --git a/todo.go b/todo.go index 869a0e44a3ce7266f65e6d2522cd3510c6bd5d70..34a7ceb339c1cc6eb8563eca8e389573f514940f 100644 --- a/todo.go +++ b/todo.go @@ -37,9 +37,9 @@ type ListCreateResponse struct { Id int } -func CheckFatal(err error) { +func CheckFatal(err error, w http.ResponseWriter) { if err != nil { - log.Fatal(err) + w.WriteHeader(http.StatusInternalServerError) } } @@ -48,9 +48,6 @@ type Database struct { } -// getURLParameter takes out the first URL parameter from the path -// path should be formated as /type/param. -// It returns a parameter representing a string. func getURLParameter(path string) *string { param := strings.Split(path, "/") if len(param) == 3 { @@ -60,30 +57,26 @@ func getURLParameter(path string) *string { } } -// getLists retrieves all the lists from the database. -// It returns a slice of List structs. -func getLists(db *sql.DB) []List { +func getLists(db *sql.DB, w http.ResponseWriter) []List { rows, err := db.Query("select * from list") - CheckFatal(err) + CheckFatal(err, w) // Retrieve all lists from the query res := make([]List, 0) for rows.Next() { list := List{} err := rows.Scan(&list.Id, &list.Name) - CheckFatal(err) + CheckFatal(err, w) res = append(res, list) } return res } -// getTasks retrieves all the tasks from the database. -// It returns a slice of Task structs. -func getTasks(db *sql.DB, listId int) []Task { +func getTasks(db *sql.DB, listId int, w http.ResponseWriter) []Task { // Query the database for all tasks that references the specified list rows, err := db.Query("select * from task where list=$1", listId) - CheckFatal(err) + CheckFatal(err, w) // Retrieve all tasks from the query res := make([]Task, 0) @@ -92,36 +85,27 @@ func getTasks(db *sql.DB, listId int) []Task { var id, list int var done bool err := rows.Scan(&id, &name, &done, &list) - CheckFatal(err) + CheckFatal(err, w) res = append(res, Task{Id: id, Name: name, Done: done, ListId: list}) } return res } -// insertList adds a list to the database with listName as its name. -// It returns the Id of the list. -func insertList(db *sql.DB, listName string) int { +func insertList(db *sql.DB, listName string, w http.ResponseWriter) int { var listId int err := db.QueryRow("insert into list (name) values ($1) returning id", listName).Scan(&listId) - CheckFatal(err) + CheckFatal(err, w) return listId } -// insertTask adds a task to the database. -// taskName specifies the name of the task, and listId the list that it belongs to. -func insertTask(db *sql.DB, taskName string, listId int) { +func insertTask(db *sql.DB, taskName string, listId int, w http.ResponseWriter) { _, err := db.Exec("insert into task (name, list) values ($1, $2)", taskName, listId) // Handle non-existing list id - CheckFatal(err) + CheckFatal(err, w) } -// listHandler manages requests with regards to the lists. -// A GET request to /list will retrieve all the lists. -// A GET request to /list/<id> will retrieve all the tasks of the list with id <id>. -// A POST request to /list will create a new list with the name provided in the Post Body -// in the format {"name": "listName"} func (db *Database) listHandler(w http.ResponseWriter, r *http.Request) { if r.Method == "GET" { // Handle GET Request @@ -130,59 +114,55 @@ func (db *Database) listHandler(w http.ResponseWriter, r *http.Request) { // If no parameter exists, retrieve all lists if param == nil || *param == "" { // Retrieve lists - list := getLists(db.Db) + list := getLists(db.Db, w) json.NewEncoder(w).Encode(&list) } else { // Get the list id from the parameter listId, err := strconv.Atoi(*param) - CheckFatal(err) + CheckFatal(err, w) // Retrieve tasks and send them back - tasks := getTasks(db.Db, listId) + tasks := getTasks(db.Db, listId, w) json.NewEncoder(w).Encode(&tasks) } } else if r.Method == "POST" { // Parse the request and create a new list body, err := ioutil.ReadAll(r.Body) - CheckFatal(err) + CheckFatal(err, w) listRequest := ListCreateRequest{} err = json.Unmarshal(body, &listRequest) - CheckFatal(err) + CheckFatal(err, w) listResponse := ListCreateResponse{} - listResponse.Id = insertList(db.Db, listRequest.Name) + listResponse.Id = insertList(db.Db, listRequest.Name, w) json.NewEncoder(w).Encode(&listResponse) } } -// taskHandler manages requests with regards to the tasks. -// A POST request to /task will create a new task with the name and list provided in -// the Post Body. The Body should be in the format {"name": "taskName", "list_id": 123} func (db *Database) taskHandler(w http.ResponseWriter, r *http.Request) { if r.Method == "POST" { body, err := ioutil.ReadAll(r.Body) - CheckFatal(err) + CheckFatal(err, w) taskRequest := CreateTaskRequest{} err = json.Unmarshal(body, &taskRequest) - CheckFatal(err) + CheckFatal(err, w) - insertTask(db.Db, taskRequest.Name, taskRequest.ListId) + insertTask(db.Db, taskRequest.Name, taskRequest.ListId, w) fmt.Fprintf(w, "OK") } } -// ConnectDb connects to a postgres database. -// it returns a database handle func ConnectDb() *sql.DB { db, err := sql.Open("postgres", "postgres://simon@localhost/todo?sslmode=disable") - CheckFatal(err) + if err != nil { + log.Fatal(err) + } return db } -// Handlers retrieves all handlers for the server. func Handlers() *http.ServeMux { db := Database{Db: ConnectDb()} mux := http.NewServeMux() @@ -195,5 +175,7 @@ func Handlers() *http.ServeMux { func main() { // Listen on port 5050 err := http.ListenAndServe(":5050", Handlers()) - CheckFatal(err) + if err != nil { + log.Fatal(err) + } }