From 65288de4fed8ac5fb28d114d2d79ce90d3f204d0 Mon Sep 17 00:00:00 2001 From: Unbewohnte Date: Wed, 22 Sep 2021 22:37:53 +0300 Subject: [PATCH] All methods implemented --- README.md | 8 +++- curl_examples | 6 +-- dbHandle/handle.go | 90 +++++++++++++++++++++++++++++++++++--- main.go | 106 +-------------------------------------------- 4 files changed, 94 insertions(+), 116 deletions(-) diff --git a/README.md b/README.md index 3fe844d..6bf8781 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,17 @@ # CRUD api ## A simple CRUD api written in Go -API has implementation of "GET", "POST", "PUT", "DELETE" http methods, allowing to Create, Read, Update and Delete objects in database via json input. +API has implementation of "GET", "POST", "PATCH", "DELETE" http methods, allowing to Create, Read, Update and Delete objects in sqlite3 database via json input. --- ## Status -Can POST a new RandomData, GET all or a specific one. +Implemented: +- **GET** +- **POST** +- **PATCH** +- **DELETE** --- diff --git a/curl_examples b/curl_examples index ecb5135..00e8c24 100644 --- a/curl_examples +++ b/curl_examples @@ -1,6 +1,6 @@ curl localhost:8000/randomdata curl localhost:8000/randomdata -H "content-type:application/json" -d '{"title":"This is a title","text":"This is a text"}' -X POST -curl localhost:8000/randomdata/1618064651615612586 -H "content-type:application/json" -d {"title":"This is an updated title","text":"This is an updated text"}' -X PUT -curl localhost:8000/randomdata/1618065099475731301 -curl localhost:8000/randomdata/1618065099475731301 -X DELETE +curl localhost:8000/randomdata/1 -H "content-type:application/json" -d {"title":"This is an updated title","text":"This is an updated text"}' -X PUT +curl localhost:8000/randomdata/1 +curl localhost:8000/randomdata/1 -X DELETE diff --git a/dbHandle/handle.go b/dbHandle/handle.go index ff7d57e..563a1a3 100644 --- a/dbHandle/handle.go +++ b/dbHandle/handle.go @@ -14,6 +14,33 @@ import ( _ "github.com/mattn/go-sqlite3" ) +// Check if a row with given id exists +func (db *DB) Exists(id uint) (bool, error) { + row, err := db.Query(fmt.Sprintf("SELECT * FROM %s WHERE id=%d", tableName, id)) + if err != nil { + return false, err + } + + // there should be only one row, because we search with id + for row.Next() { + var realID uint + var title string + var text string + var dateCreated int64 + var lastUpdated int64 + + row.Scan(&realID, &title, &text, &dateCreated, &lastUpdated) + + fmt.Printf("real %d --- given %d\n", realID, id) + + if realID == id { + return true, nil + } + } + + return false, nil +} + // Collect and return all rows in db func (db *DB) GetEverything() ([]*randomdata.RandomData, error) { rows, err := db.Query(fmt.Sprintf("SELECT * FROM %s", tableName)) @@ -78,11 +105,23 @@ func (db *DB) GetSpecific(id uint) (*randomdata.RandomData, error) { // Delete `RandomData` from db with given id func (db *DB) DeleteSpecific(id uint) error { + _, err := db.Exec(fmt.Sprintf("DELETE FROM %s WHERE id=%d", tableName, id)) + if err != nil { + return err + } + return nil } -// Edit `Randomdata` from db with given id -func (db *DB) PatchSpecific(id uint) error { +// Replace `Randomdata` in db with given id with a new one. +// Does not affect `DateCreated` +func (db *DB) UpdateSpecific(id uint, newRD randomdata.RandomData) error { + // `DateCreated` won`t be changed because we`re patching an already existing thing + _, err := db.Exec(fmt.Sprintf("UPDATE %s SET title='%s', text='%s', last_updated=%d WHERE id=%d", tableName, newRD.Title, newRD.Text, newRD.LastUpdated, id)) + if err != nil { + return err + } + return nil } @@ -130,7 +169,6 @@ func (db *DB) HandleGlobalWeb(w http.ResponseWriter, r *http.Request) { log.Printf("Could not create a row: %s", err) } w.WriteHeader(http.StatusAccepted) - return case http.MethodGet: randomDatas, err := db.GetEverything() @@ -147,11 +185,9 @@ func (db *DB) HandleGlobalWeb(w http.ResponseWriter, r *http.Request) { } w.Write(randomDatasJsonBytes) - return default: w.WriteHeader(http.StatusMethodNotAllowed) - return } } @@ -180,14 +216,54 @@ func (db *DB) HandleSpecificWeb(w http.ResponseWriter, r *http.Request) { if err != nil { w.WriteHeader(http.StatusInternalServerError) log.Printf("Could not convert RandomData to Json: %s\n", err) + return } w.Write(rdJsonBytes) - return + + case http.MethodDelete: + err := db.DeleteSpecific(uint(providedID)) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + log.Printf("Could not delete from db: %s\n", err) + return + } + + case http.MethodPatch: + if r.Header.Get("content-type") != "application/json" { + w.WriteHeader(http.StatusUnsupportedMediaType) + return + } + + defer r.Body.Close() + + body, err := io.ReadAll(r.Body) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + return + } + + var randomData randomdata.RandomData + err = json.Unmarshal(body, &randomData) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + return + } + + // create date created, last updated + randomData.LastUpdated = time.Now().UTC().Unix() + + err = db.UpdateSpecific(uint(providedID), randomData) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + log.Printf("Could not update a RandomData: %s\n", err) + return + } + + w.WriteHeader(http.StatusAccepted) default: w.WriteHeader(http.StatusMethodNotAllowed) - return } } diff --git a/main.go b/main.go index e0a7224..8167b0d 100644 --- a/main.go +++ b/main.go @@ -14,7 +14,7 @@ import ( var ( port *uint = flag.Uint("port", 8080, "Specifies a port on which the helping page will be served") dbname string = "database.db" - tableName = "randomdata" + tableName string = "randomdata" ) func init() { @@ -35,6 +35,7 @@ func main() { } log.Printf("Created %s db\n", tableName) + // set up patterns and handlers mux := http.NewServeMux() mux.HandleFunc("/", helpPage) mux.HandleFunc("/randomdata", db.HandleGlobalWeb) @@ -65,106 +66,3 @@ func helpPage(w http.ResponseWriter, r *http.Request) { ` fmt.Fprint(w, helpMessage) } - -// func (dbHandler *randomDataHandler) updateSpecificRandomData(w http.ResponseWriter, r *http.Request) { -// if r.Header.Get("content-type") != "application/json" { -// w.WriteHeader(http.StatusUnsupportedMediaType) -// w.Write([]byte(fmt.Sprintf("Got `%s` instead of `application/json`", r.Header.Get("content-type")))) -// return -// } - -// requestBody, err := io.ReadAll(r.Body) -// if err != nil { -// log.Println("Error reading http request (create) : ", err) -// w.WriteHeader(http.StatusBadRequest) -// r.Body.Close() -// return -// } -// defer r.Body.Close() - -// var givenUpdatedRandomData RandomData -// err = json.Unmarshal(requestBody, &givenUpdatedRandomData) -// if err != nil { -// log.Println("Error unmarshalling request body (updateSpecificRandomData) : ", err) -// return -// } - -// givenID := strings.Split(r.URL.String(), "/")[2] - -// dbBytes, err := dbHandler.readDatabase() -// if err != nil { -// log.Println("Error reading db (updateSpecificRandomData) : ", err) -// w.WriteHeader(http.StatusInternalServerError) -// return -// } -// var db []RandomData - -// err = json.Unmarshal(dbBytes, &db) -// if err != nil { -// log.Println("Error unmarshalling database (update) : ", err) -// return -// } - -// int64GivenID, _ := strconv.ParseInt(givenID, 10, 64) -// var counter int64 -// for _, randomData := range db { -// if int64GivenID == randomData.ID { -// var updatedRandomData RandomData - -// updatedRandomData = givenUpdatedRandomData -// updatedRandomData.ID = randomData.ID -// updatedRandomData.DateCreated = randomData.DateCreated -// updatedRandomData.LastUpdated = time.Now().UTC() - -// dbHandler.removeRandomData(int64GivenID) -// dbHandler.writeRandomData(updatedRandomData) - -// log.Printf("Successfully updated RandomData with id %v \n", updatedRandomData.ID) -// return -// } -// counter++ -// } - -// w.WriteHeader(http.StatusNotFound) -// } - -// func (dbHandler *randomDataHandler) deleteSpecificRandomData(w http.ResponseWriter, r *http.Request) { -// givenID := strings.Split(r.URL.String(), "/")[2] - -// int64GivenID, _ := strconv.ParseInt(givenID, 10, 64) - -// err := dbHandler.removeRandomData(int64GivenID) -// if err != nil { -// log.Println("Error removing RandomData (deleteSpecificRandomData) : ", err) -// w.WriteHeader(http.StatusInternalServerError) -// return -// } - -// w.WriteHeader(http.StatusOK) - -// log.Printf("Successfully deleted RandomData with id %v \n", int64GivenID) -// } - -// func (dbHandler *randomDataHandler) handle(w http.ResponseWriter, r *http.Request) { -// switch r.Method { -// case "GET": -// dbHandler.get(w, r) -// case "POST": -// dbHandler.create(w, r) -// default: -// w.WriteHeader(http.StatusMethodNotAllowed) -// } -// } - -// func (dbHandler *randomDataHandler) handleSpecific(w http.ResponseWriter, r *http.Request) { -// switch r.Method { -// case "GET": -// dbHandler.getSpecificRandomData(w, r) -// case "PUT": -// dbHandler.updateSpecificRandomData(w, r) -// case "DELETE": -// dbHandler.deleteSpecificRandomData(w, r) -// default: -// w.WriteHeader(http.StatusMethodNotAllowed) -// } -// }