-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(): adds support for CRUD over libraries
- Loading branch information
0 parents
commit ea89b25
Showing
3 changed files
with
200 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package main | ||
|
||
import ( | ||
"net/http" | ||
"time" | ||
|
||
"github.com/pborman/uuid" | ||
) | ||
|
||
// Book is the representation of a book | ||
type Book struct { | ||
ID uuid.UUID `json:"id" gorm:"primary_key"` | ||
Name string `json:"name"` | ||
Author string `json:"author"` | ||
PublishedDate time.Time `json:"publishedDate"` | ||
} | ||
|
||
func getBooks(w http.ResponseWriter, r *http.Request) { | ||
} | ||
|
||
func createBook(w http.ResponseWriter, r *http.Request) { | ||
} | ||
|
||
func updateBook(w http.ResponseWriter, r *http.Request) { | ||
} | ||
|
||
func getOneBook(w http.ResponseWriter, r *http.Request) { | ||
} | ||
|
||
func deleteOneBook(w http.ResponseWriter, r *http.Request) { | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
package main | ||
|
||
import ( | ||
"encoding/json" | ||
"io" | ||
"net/http" | ||
|
||
"github.com/gorilla/mux" | ||
"github.com/pborman/uuid" | ||
) | ||
|
||
// Library is the representation of a library | ||
type Library struct { | ||
ID string `json:"id" sql:"type:varchar(36);primary key" gorm:"primary_key"` | ||
Name string `json:"name"` | ||
Address string `json:"address"` | ||
Phone string `json:"phone"` | ||
} | ||
|
||
func getLibraries(w http.ResponseWriter, r *http.Request) { | ||
var libraries []Library | ||
db.Find(&libraries) | ||
writeJSON(w, libraries) | ||
} | ||
|
||
func createLibrary(w http.ResponseWriter, r *http.Request) { | ||
newLibrary, err := libraryFromJSON(r.Body) | ||
if err != nil { | ||
http.Error(w, "Invalid JSON provided", http.StatusBadRequest) | ||
return | ||
} | ||
validationErrs := validateLibrary(*newLibrary) | ||
if len(validationErrs) > 0 { | ||
w.WriteHeader(http.StatusBadRequest) | ||
writeJSON(w, validationErrs) | ||
return | ||
} | ||
newLibrary.ID = uuid.NewUUID().String() | ||
db.Create(newLibrary) | ||
w.Header().Set("Library-Id", newLibrary.ID) | ||
w.WriteHeader(201) | ||
} | ||
|
||
func updateLibrary(w http.ResponseWriter, r *http.Request) { | ||
var library Library | ||
requestVars := mux.Vars(r) | ||
db.Where("id = ?", requestVars["libraryId"]).Find(&library) | ||
if library.ID == "" { | ||
http.Error(w, "", http.StatusNotFound) | ||
return | ||
} | ||
|
||
update, err := libraryFromJSON(r.Body) | ||
if err != nil { | ||
http.Error(w, "Invalid JSON provided", http.StatusBadRequest) | ||
return | ||
} | ||
library.Name = update.Name | ||
library.Address = update.Address | ||
library.Phone = update.Phone | ||
|
||
validationErrs := validateLibrary(library) | ||
if len(validationErrs) > 0 { | ||
w.WriteHeader(http.StatusBadRequest) | ||
writeJSON(w, validationErrs) | ||
return | ||
} | ||
|
||
writeJSON(w, library) | ||
} | ||
|
||
func getOneLibrary(w http.ResponseWriter, r *http.Request) { | ||
var library Library | ||
requestVars := mux.Vars(r) | ||
db.Where("id = ?", requestVars["libraryId"]).Find(&library) | ||
if library.ID == "" { | ||
http.Error(w, "", http.StatusNotFound) | ||
return | ||
} | ||
writeJSON(w, library) | ||
} | ||
|
||
func deleteLibrary(w http.ResponseWriter, r *http.Request) { | ||
requestVars := mux.Vars(r) | ||
db.Where("id = ?", requestVars["libraryId"]).Delete(&Library{}) | ||
w.WriteHeader(http.StatusNoContent) | ||
} | ||
|
||
func libraryFromJSON(data io.ReadCloser) (*Library, error) { | ||
var library = new(Library) | ||
decoder := json.NewDecoder(data) | ||
err := decoder.Decode(library) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return library, nil | ||
} | ||
|
||
func validateLibrary(library Library) (errs []string) { | ||
if library.Name == "" { | ||
errs = append(errs, "The name is required") | ||
} | ||
if library.Address == "" { | ||
errs = append(errs, "The address is required") | ||
} | ||
if library.Phone == "" { | ||
errs = append(errs, "The phone is required") | ||
} | ||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package main | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"log" | ||
"net/http" | ||
"sync" | ||
|
||
"github.com/gorilla/mux" | ||
"github.com/jinzhu/gorm" | ||
_ "github.com/jinzhu/gorm/dialects/mysql" | ||
) | ||
|
||
var db *gorm.DB | ||
|
||
func main() { | ||
initDatabase() | ||
defer db.Close() | ||
|
||
router := mux.NewRouter() | ||
apiRouter := router.PathPrefix("/api").Subrouter() | ||
apiRouter.HandleFunc("/libraries", getLibraries).Methods("GET") | ||
apiRouter.HandleFunc("/libraries", createLibrary).Methods("POST") | ||
apiRouter.HandleFunc("/libraries/{libraryId}", updateLibrary).Methods("PUT") | ||
apiRouter.HandleFunc("/libraries/{libraryId}", getOneLibrary).Methods("GET") | ||
apiRouter.HandleFunc("/libraries/{libraryId}", deleteLibrary).Methods("DELETE") | ||
apiRouter.HandleFunc("/libraries/{libraryId}/books", getBooks).Methods("GET") | ||
apiRouter.HandleFunc("/libraries/{libraryId}/books", createBook).Methods("GET") | ||
apiRouter.HandleFunc("/libraries/{libraryId}/books/{bookId}", updateBook).Methods("PUT") | ||
apiRouter.HandleFunc("/libraries/{libraryId}/books/{bookId}", getOneBook).Methods("GET") | ||
apiRouter.HandleFunc("/libraries/{libraryId}/books/{bookId}", deleteOneBook).Methods("DELETE") | ||
|
||
http.Handle("/", router) | ||
fmt.Println("Application started on port 8080") | ||
log.Fatal(http.ListenAndServe(":8080", nil)) | ||
} | ||
|
||
var initContext sync.Once | ||
|
||
func initDatabase() { | ||
initContext.Do(func() { | ||
var err error | ||
db, err = gorm.Open("mysql", "root:root@/books_api?charset=utf8&parseTime=True&loc=Local") | ||
if err != nil { | ||
log.Fatalf("Fail to connect to db: %v", err) | ||
} | ||
}) | ||
} | ||
|
||
func writeJSON(w http.ResponseWriter, data interface{}) { | ||
bytes, err := json.Marshal(data) | ||
if err != nil { | ||
log.Printf("error while encoding json: %v", err) | ||
return | ||
} | ||
w.Header().Set("Content-Type", "application/json") | ||
w.Write(bytes) | ||
} |