// returnSession returns an existing gameSession response to the response. func returnGameSession(c web.C, w http.ResponseWriter, r *http.Request) { // Find the gameSession by the id parameter in the url gameSession, err := GetGameSessionBy("_id", bson.ObjectIdHex(c.URLParams["id"])) // GameSession could not be found if err != nil { io.WriteString(w, c.URLParams["id"]+" "+err.Error()) w.WriteHeader(404) return } // Then we want to actually find the game game, err := GetGameBy("_id", bson.ObjectIdHex(gameSession.GameId)) // Game could not be found if err != nil { io.WriteString(w, "game "+gameSession.GameId+" not found") w.WriteHeader(404) return } gameSessionResource := hal.NewResource(gameSession, "/sessions/"+gameSession.ID.Hex()) gameResource := hal.NewResource(game, "/games/"+gameSession.GameId) gameSessionResource.Embed("game", gameResource) gameSessionResource.AddNewLink("game", "/games/"+gameSession.GameId) j, _ := json.Marshal(gameSessionResource) io.WriteString(w, string(j)) }
func main() { c := Category{ Code: 1, Name: "Some Category", } p := Product{ Code: 1, Name: "Some Product", Price: 10, Category: c, } // Creating HAL Resources pr := hal.NewResource(p, "/products/1") cr1 := hal.NewResource(p.Category, "/categories/1") cr2 := hal.NewResource(p.Category, "/categories/2") cr3 := hal.NewResource(p.Category, "/categories/3") // Embeding categories into product pr.Embed("categories", cr1) pr.Embedded.Del("categories") pr.Embedded.Set("categories", cr2) pr.Embedded.Add("categories", cr3) // JSON Encoding j, err := json.MarshalIndent(pr, "", " ") if err != nil { fmt.Printf("%s", err) } fmt.Printf("%s", j) }
func newUser(w http.ResponseWriter, r *http.Request) { var user User // Read the user information out of the post body. body, _ := ioutil.ReadAll(r.Body) err := json.Unmarshal(body, &user) // Missing POST data if err != nil { w.WriteHeader(400) io.WriteString(w, errorResponse([]string{"Request Data does not match expected format"})) return } // Search for use by email to see if they already exist userCollection := DB.C("users") err = userCollection.Find(bson.M{"email": user.Email}).One(&user) // User was found if err == nil { w.WriteHeader(409) io.WriteString(w, errorResponse([]string{"User Exists"})) return } // Something else went wrong if err != mgo.ErrNotFound { w.WriteHeader(500) io.WriteString(w, errorResponse([]string{"Something really bad went wrong"})) } // Update the ser createdAt and insert the user user.CreatedAt = time.Now() err = userCollection.Insert(user) if err != nil { w.WriteHeader(500) io.WriteString(w, errorResponse([]string{err.Error()})) return } // Find the user by email to ensure it saved properly savedUser, err := GetUserBy("email", user.Email) // Something went wrong we couldn't find the saved user if err != nil { w.WriteHeader(400) io.WriteString(w, errorResponse([]string{"User did not save properly"})) return } userResponse := hal.NewResource(savedUser, "/users/"+savedUser.ID.Hex()) j, _ := json.Marshal(userResponse) io.WriteString(w, string(j)) }
// root route (GET "/"). func root(w http.ResponseWriter, r *http.Request) { entrypoint := hal.NewResource(struct{}{}, "/") for name, path := range routes { entrypoint.AddNewLink(name, path) } j, _ := json.Marshal(entrypoint) io.WriteString(w, string(j)) }
func main() { // Creating HAL Resources r := hal.NewResource(Response{Count: 10, Total: 20}, "/tasks") r.AddNewLink("next", "/tasks=page=2") t1 := hal.NewResource(Task{Id: 1, Name: "Some Task"}, "/tasks/1") t2 := hal.NewResource(Task{Id: 2, Name: "Some Task"}, "/tasks/2") t3 := hal.NewResource(Task{Id: 3, Name: "Some Task"}, "/tasks/3") // Embeding tasks r.Embed("tasks", t1) r.Embed("tasks", t2) r.Embed("tasks", t3) // JSON Encoding j, err := json.MarshalIndent(r, "", " ") if err != nil { fmt.Printf("%s", err) } fmt.Printf("%s", j) }
// Responds to a POST request to create a new game func newGame(w http.ResponseWriter, r *http.Request) { var game Game // Ensure the post body is available and is in correct JSON format body, _ := ioutil.ReadAll(r.Body) err := json.Unmarshal(body, &game) // Missing POST data if err != nil { w.WriteHeader(400) io.WriteString(w, errorResponse([]string{"json data is invalid"})) return } // Search the games collection to see if a game with this name already exists gameCollection := DB.C("games") _, err = GetGameBy("name", game.Name) // Game was found so we need to freak out. if err == nil { w.WriteHeader(409) io.WriteString(w, errorResponse([]string{game.Name + " already exists as a game"})) return } // Save the game to the database err = gameCollection.Insert(game) if err != nil { w.WriteHeader(400) io.WriteString(w, errorResponse([]string{err.Error()})) return } // If the game saved properly we want to fetch it back out savedGame, err := GetGameBy("name", game.Name) // Something went wrong and the game apparently wasn't saved properly if err != nil { w.WriteHeader(400) io.WriteString(w, errorResponse([]string{"Game did not save properly"})) return } gameResponse := hal.NewResource(savedGame, "/games/"+savedGame.ID.Hex()) gameResponse.AddNewLink("sessions", "/sessions?gameId="+savedGame.ID.Hex()) j, _ := json.Marshal(gameResponse) io.WriteString(w, string(j)) }
// returnUser returns an existing user response to the response. func returnUser(c web.C, w http.ResponseWriter, r *http.Request) { user, err := GetUserBy("_id", bson.ObjectIdHex(c.URLParams["id"])) // Something went wrong if err != nil { io.WriteString(w, c.URLParams["id"]+" "+err.Error()) w.WriteHeader(404) return } userResponse := hal.NewResource(user, "/users/"+user.ID.Hex()) j, _ := json.Marshal(userResponse) io.WriteString(w, string(j)) }
// returnGame returns an existing game response to the response. func returnGame(c web.C, w http.ResponseWriter, r *http.Request) { // Find the game by the id parameter in the url game, err := GetGameBy("_id", bson.ObjectIdHex(c.URLParams["id"])) // Game could not be found if err != nil { io.WriteString(w, c.URLParams["id"]+" "+err.Error()) w.WriteHeader(404) return } gameResponse := hal.NewResource(game, "/games/"+game.ID.Hex()) gameResponse.AddNewLink("sessions", "/sessions?gameId="+game.ID.Hex()) j, _ := json.Marshal(gameResponse) io.WriteString(w, string(j)) }
func main() { p := Product{ Code: 1, Name: "Some Product", Price: 10, } // Creating HAL Resources pr := hal.NewResource(p, "/products/1") // Adding an extra link pr.AddNewLink("help", "/docs") // JSON Encoding j, err := json.MarshalIndent(pr, "", " ") if err != nil { fmt.Printf("%s", err) } fmt.Printf("%s", j) }
// returnGame returns all existing games // Filters: // page // limit func returnGames(c web.C, w http.ResponseWriter, r *http.Request) { // Get the page limit parameter and the current page parameter currentPage, _ := strconv.Atoi(r.URL.Query().Get("page")) if currentPage == 0 { currentPage = 1 } pageLimit, _ := strconv.Atoi(r.URL.Query().Get("limit")) if pageLimit == 0 { pageLimit = 10 } else if pageLimit > 100 { pageLimit = 100 } var games []Game // Get the count of pages and total games totalGames, err := DB.C("games").Count() totalPages := int(math.Ceil(float64(totalGames) / float64(pageLimit))) if err != nil { w.WriteHeader(401) return } // Start the query to find all the games query := DB.C("games").Find(bson.M{}) // Modifications to the query to allow pagination if currentPage > 1 { query.Skip((currentPage - 1) * pageLimit) } query.Limit(pageLimit).All(&games) // We found no games if err != nil { io.WriteString(w, c.URLParams["id"]+" "+err.Error()) w.WriteHeader(404) return } gameResponse := hal.NewResource(Collection{ Count: len(games), Total: totalGames, }, "/games?page="+strconv.Itoa(currentPage)) // Embed the pagination links if currentPage > 1 { gameResponse.AddNewLink("previous", "/games?page="+strconv.Itoa(currentPage-1)) } if currentPage < totalPages { gameResponse.AddNewLink("next", "/games?page="+strconv.Itoa(currentPage+1)) gameResponse.AddNewLink("last", "/games?page="+strconv.Itoa(totalPages)) } // Add session linke to the games for _, game := range games { g := hal.NewResource(game, "/games/"+game.ID.Hex()) g.AddNewLink("sessions", "/sessions?gameId="+game.ID.Hex()) gameResponse.Embed("games", g) } j, _ := json.Marshal(gameResponse) io.WriteString(w, string(j)) }
// returnSession returns all existing sessions // Filters: // gameId // page // limit func returnGameSessions(c web.C, w http.ResponseWriter, r *http.Request) { var sessions []GameSession var totalSessions int var query *mgo.Query var err error var game *Game // Fetch the gameId filter if it is set gameId := r.URL.Query().Get("gameId") currentPage, _ := strconv.Atoi(r.URL.Query().Get("page")) if currentPage == 0 { currentPage = 1 } pageLimit, _ := strconv.Atoi(r.URL.Query().Get("limit")) if pageLimit == 0 { pageLimit = 10 } else if pageLimit > 100 { pageLimit = 100 } // Alter the query depending on if we have that gameId filter if len(gameId) > 0 { totalSessions, err = DB.C("gameSessions").Find(bson.M{"gameId": gameId}).Count() query = DB.C("gameSessions").Find(bson.M{"gameId": gameId}) // Then we want to actually find the game game, err = GetGameBy("_id", bson.ObjectIdHex(gameId)) // Game could not be found if err != nil { io.WriteString(w, "game "+gameId+" not found") w.WriteHeader(404) return } } else { totalSessions, err = DB.C("gameSessions").Count() query = DB.C("gameSessions").Find(bson.M{}) } totalPages := int(math.Ceil(float64(totalSessions) / float64(pageLimit))) if currentPage > 1 { query.Skip((currentPage - 1) * pageLimit) } // Find all sessions up to the limit err = query.Limit(pageLimit).All(&sessions) // Something went wrong if err != nil { io.WriteString(w, c.URLParams["id"]+" "+err.Error()) w.WriteHeader(404) return } sessionResponse := hal.NewResource(Collection{ Count: len(sessions), Total: totalSessions, }, "/sessions?page="+strconv.Itoa(currentPage)) // Link to the game information on the session for _, session := range sessions { s := hal.NewResource(session, "/sessions/"+session.ID.Hex()) s.AddNewLink("game", "/games/"+session.GameId) // If the query has a gameId filter we want to embed that game into // each session. if len(gameId) > 0 { g := hal.NewResource(game, "/games/"+game.ID.Hex()) s.Embed("game", g) } sessionResponse.Embed("sessions", s) } // Add the num pages links if currentPage > 1 { sessionResponse.AddNewLink("previous", "/sessions?page="+strconv.Itoa(currentPage-1)) } if currentPage < totalPages { sessionResponse.AddNewLink("next", "/sessions?page="+strconv.Itoa(currentPage+1)) sessionResponse.AddNewLink("last", "/sessions?page="+strconv.Itoa(totalPages)) } j, _ := json.Marshal(sessionResponse) io.WriteString(w, string(j)) }
func newRound(c web.C, w http.ResponseWriter, r *http.Request) { var round Round // read the post body and get the data for the round into a round struct body, _ := ioutil.ReadAll(r.Body) err := json.Unmarshal(body, &round) // Missing POST data if err != nil { w.WriteHeader(400) io.WriteString(w, errorResponse([]string{"Request Data does not match expected format"})) return } // Find the game session this round belongs to gameSession, err := GetGameSessionBy("_id", bson.ObjectIdHex(round.GameSessionId)) if err != nil { w.WriteHeader(400) io.WriteString(w, err.Error()) io.WriteString(w, errorResponse([]string{"GameSession for round not found"})) return } // Detmine the number of rounds already in the game. roundCount := len(gameSession.Rounds) round.CreatedAt = time.Now() // Lets add this round to the collection of rounds shall we? gameSession.Rounds = append(gameSession.Rounds, round) gameSessionCollection := DB.C("gameSessions") // Update the game session record err = gameSessionCollection.Update(bson.M{"_id": bson.ObjectIdHex(round.GameSessionId)}, gameSession) if err != nil { w.WriteHeader(400) io.WriteString(w, errorResponse([]string{err.Error()})) return } // Fetch back the game session to validate it saved properly savedGS, err := GetGameSessionBy("_id", bson.ObjectIdHex(round.GameSessionId)) // Something went wrong if err != nil { w.WriteHeader(400) io.WriteString(w, errorResponse([]string{"Round did not save properly"})) return } //We didn't add the round to the session if len(savedGS.Rounds)-1 != roundCount { w.WriteHeader(400) io.WriteString(w, errorResponse([]string{"Round did not save properly"})) return } gsResponse := hal.NewResource(savedGS, "/sessions/"+savedGS.ID.Hex()) // Add player information to the game session for _, playerId := range savedGS.CountryPlayers { user, _ := GetUserBy("_id", bson.ObjectIdHex(playerId)) gsResponse.Embed("players", hal.NewResource(user, "/users/"+user.ID.Hex())) } j, _ := json.Marshal(gsResponse) io.WriteString(w, string(j)) }
// newGameSession responds to a post request and create a new game session // for a particular game. func newGameSession(w http.ResponseWriter, r *http.Request) { var gameSession GameSession // Read the post body body, _ := ioutil.ReadAll(r.Body) // Unmarshal the json into the gameSession struct err := json.Unmarshal(body, &gameSession) // Missing required POST data to create a session if err != nil { w.WriteHeader(400) io.WriteString(w, errorResponse([]string{"Request Data does not match expected format"})) return } // Find the game associated with the session game, err := GetGameBy("_id", bson.ObjectIdHex(gameSession.GameId)) // If the game does not exist, bork if err != nil { w.WriteHeader(400) io.WriteString(w, err.Error()) io.WriteString(w, errorResponse([]string{"Game for game session not found"})) return } now := time.Now() gameSession.CreatedAt = now gameSessionCollection := DB.C("gameSessions") // Add the session to the db err = gameSessionCollection.Insert(gameSession) if err != nil { w.WriteHeader(400) io.WriteString(w, errorResponse([]string{err.Error()})) return } var savedGS GameSession // Try to fetch the saved session back err = gameSessionCollection.Find(bson.M{ "userId": gameSession.UserId, "createdAt": gameSession.CreatedAt, }).One(&savedGS) // Something went wrong the session didn't save right if err != nil { w.WriteHeader(400) io.WriteString(w, errorResponse([]string{"GameSession did not save properly"})) return } gameSessionResponse := hal.NewResource(savedGS, "/sessions/"+savedGS.ID.Hex()) // Embed the countries and user information to the response for countryName, playerId := range savedGS.CountryPlayers { user, _ := GetUserBy("_id", bson.ObjectIdHex(playerId)) for _, country := range game.Countries { if countryName == country.Name { gameSessionResponse.Embed("countries", hal.NewResource(country, "")) } } gameSessionResponse.Embed("players", hal.NewResource(user, "/users/"+user.ID.Hex())) } j, _ := json.Marshal(gameSessionResponse) io.WriteString(w, string(j)) }
// returnUser returns all existing users // Filters: // page // limit func returnUsers(c web.C, w http.ResponseWriter, r *http.Request) { //Setup the page and limit values currentPage, _ := strconv.Atoi(r.URL.Query().Get("page")) if currentPage == 0 { currentPage = 1 } pageLimit, _ := strconv.Atoi(r.URL.Query().Get("limit")) if pageLimit == 0 { pageLimit = 10 } else if pageLimit > 100 { pageLimit = 100 } var users []User // Get the total number os users and total number of pages totalUsers, err := DB.C("users").Count() totalPages := int(math.Ceil(float64(totalUsers) / float64(pageLimit))) // Thats not great ¯\_(ツ)_/¯ if err != nil { io.WriteString(w, c.URLParams["id"]+" "+err.Error()) w.WriteHeader(401) return } // Begin the find all users query query := DB.C("users").Find(bson.M{}) // Filter the query by page if currentPage > 1 { query.Skip((currentPage - 1) * pageLimit) } // Limit the query query.Limit(pageLimit).All(&users) // Something went wrong if err != nil { w.WriteHeader(404) return } userResponse := hal.NewResource(Collection{ Count: len(users), Total: totalUsers, }, "/users?page="+strconv.Itoa(currentPage)) // Add pagination links to the response if currentPage > 1 { userResponse.AddNewLink("previous", "/users?page="+strconv.Itoa(currentPage-1)) } if currentPage < totalPages { userResponse.AddNewLink("next", "/users?page="+strconv.Itoa(currentPage+1)) userResponse.AddNewLink("last", "/users?page="+strconv.Itoa(totalPages)) } // Embed the users to the collection for _, user := range users { userResponse.Embed("users", hal.NewResource(user, "/users/"+user.ID.Hex())) } j, _ := json.Marshal(userResponse) io.WriteString(w, string(j)) }