Go
Golang is a programming language initially developed at Google in year 2007 by Robert Griesemer, Rob Pike, and Ken Thompson. Go programming language is a statically-typed language with syntax similar to that of C. It provides garbage collection, type safety, dynamic-typing capability, many advanced built-in types such as variable length arrays and key-value maps. It also provides a rich standard library.
MongoDB
MongoDB is a free and open-source cross-platform document-oriented database program. Classified as a NoSQLdatabase program, MongoDB uses JSON-like documents with schemas.
RESTAPI
One of the most popular types of API is REST or, as they’re sometimes known, RESTful APIs. REST or RESTful APIs were designed to take advantage of existing protocols. While REST – or Representational State Transfer – can be used over nearly any protocol, when used for web APIs it typically takes advantage of HTTP. This means that developers have no need to install additional software or libraries when creating a REST API
Installation of MongoDB Server:
Import they GPG key for the official MongoDB repository.
$ sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10
Add the MongoDB repository details so APT
$ echo "deb http://repo.mongodb.org/apt/ubuntu "$(lsb_release -sc)"/mongodb-org/3.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.0.list
After adding the repository details, we need to update the packages list.
$ sudo apt-get update
Install MongoDB
$ sudo apt-get install -y mongodb-org
Installation of Go:
Download the latest package for Go by running this command, which will pull down the Go package file, and save it to your current working directory.
$ sudo curl -O https://storage.googleapis.com/golang/go1.6.linux-amd64.tar.gz
Now we can set the Go paths
$ sudo vi ~/.profile
At the end of the file, add this line:
export GOROOT=$HOME/go export PATH=$PATH:$GOROOT/bin
With the appropriate line pasted into your profile, save and close the file. Next, refresh your profile by running:
$ source ~/.profile
Build RESTful API in Go and MongoDB
The REST API service will create endpoints to manage a store of movies. The operations that our endpoints will allow are:
GET /movies Get list of movies
GET /movies/:id Find a movie by it’s id
POST /movies Create a new movie
Before we begin, we need to get the packages to setup the API:
- toml : Parse the configuration file (MongoDB server & credentials)
- mux : Request router and dispatcher for matching incoming requests to their respective handler
- mgo : MongoDB driver
$ go get github.com/BurntSushi/toml gopkg.in/mgo.v2 github.com/gorilla/mux
After installing the dependencies, we create a file called “app.go“, with the following content:
package main import (import ( "fmt" "log" "net/http" "github.com/gorilla/mux") func AllMoviesEndPoint(w http.ResponseWriter, r *http.Request) {func AllMoviesEndPoint(w http.ResponseWriter, r *http.Request) { movies, err := dao.FindAll() if err != nil { respondWithError(w, http.StatusInternalServerError, err.Error()) return } respondWithJson(w, http.StatusOK, movies)} func FindMovieEndpoint(w http.ResponseWriter, r *http.Request) { params := mux.Vars(r) movie, err := dao.FindById(params["id"]) if err != nil { respondWithError(w, http.StatusBadRequest, "Invalid Movie ID") return respondWithJson(w, http.StatusOK, movie)} func CreateMovieEndPoint(w http.ResponseWriter, r *http.Request) { defer r.Body.Close() var movie Movie if err := json.NewDecoder(r.Body).Decode(&movie); err != nil { respondWithError(w, http.StatusBadRequest, "Invalid request payload") return } movie.ID = bson.NewObjectId() if err := dao.Insert(movie); err != nil { respondWithError(w, http.StatusInternalServerError, err.Error()) return } respondWithJson(w, http.StatusCreated, movie) func UpdateMovieEndPoint(w http.ResponseWriter, r *http.Request) { defer r.Body.Close() var movie Movie if err := json.NewDecoder(r.Body).Decode(&movie); err != nil { respondWithError(w, http.StatusBadRequest, "Invalid request payload") return } if err := dao.Update(movie); err != nil { respondWithError(w, http.StatusInternalServerError, err.Error()) returnrespondWithJson(w, http.StatusOK, map[string]string{"result": "success"})}func DeleteMovieEndPoint(w http.ResponseWriter, r *http.Request) { defer r.Body.Close() var movie Movie if err := json.NewDecoder(r.Body).Decode(&movie); err != nil { respondWithError(w, http.StatusBadRequest, "Invalid request payload") return } if err := dao.Delete(movie); err != nil { respondWithError(w, http.StatusInternalServerError, err.Error()) return } respondWithJson(w, http.StatusOK, map[string]string{"result": "success"})}func main() { r := mux.NewRouter() r.HandleFunc("/movies", AllMoviesEndPoint).Methods("GET") r.HandleFunc("/movies", CreateMovieEndPoint).Methods("POST") r.HandleFunc("/movies", UpdateMovieEndPoint).Methods("PUT") r.HandleFunc("/movies", DeleteMovieEndPoint).Methods("DELETE") r.HandleFunc("/movies/{id}", FindMovieEndpoint).Methods("GET") if err := http.ListenAndServe(":3000", r); err != nil { log.Fatal(err) }}
The above code will create a controller for each endpoint, then make an HTTP server on port 3000.
Now create a basic Moviemodel. In Go, we use struct keyword to create a model:
type Movie struct { ID bson.ObjectId `bson:"_id" json:"id"` Name string `bson:"name" json:"name"` CoverImage string `bson:"cover_image" json:"cover_image"` Description string `bson:"description" json:"description"`}
Create the Data Access Object to manage database operations.
package dao import ( "log" "github.com/mlabouardy/movies-restapi/models" mgo "gopkg.in/mgo.v2" mgo "gopkg.in/mgo.v2" "gopkg.in/mgo.v2/bson" ) type MoviesDAO struct { Server string Database string } var db *mgo.Database const ( COLLECTION = "movies" ) func (m *MoviesDAO) Connect() { session, err := mgo.Dial(m.Server) if err != nil { log.Fatal(err) } db = session.DB(m.Database) } ffunc (m *MoviesDAO) FindAll() ([]Movie, error) { var movies []Movie err := db.C(COLLECTION).Find(bson.M{}).All(&movies) return movies, err } func (m *MoviesDAO) FindById(id string) (Movie, error) { var movie Movie err := db.C(COLLECTION).FindId(bson.ObjectIdHex(id)).One(&movie) return movie, err } func (m *MoviesDAO) Insert(movie Movie) error { err := db.C(COLLECTION).Insert(&movie) return err } func (m *MoviesDAO) Delete(movie Movie) error { err := db.C(COLLECTION).Remove(&movie) return err } func (m *MoviesDAO) Update(movie Movie) error { err := db.C(COLLECTION).UpdateId(movie.ID, &movie) return err }
To run the server in local, type the following command:
$ go run app.go
Create a Movie
List of Movies