前回から引きつづいて、今度はDELETE用のAPIを実装していく。
コメント削除用のAPI
REST的には削除対象はURLで表現する形になるので、今回もそれにならったAPIとする。
http://localhost:8080/1/remark/delete/[コメントのID]
サーバーサイド
API的にはgetに似ているけど、コード自体もかなりgetと似た形になる。
...
func init() {
http.HandleFunc("/", errorHandler(root))
http.HandleFunc("/1/remark/post/", errorHandler(postRemark))
http.HandleFunc("/1/remark/get/", errorHandler(getRemark))
http.HandleFunc("/1/remark/delete/", errorHandler(deleteRemark))
}
...
func getRemarkID(path string) (int64, bool) {
split := strings.Split(path, "/", -1)
length := len(split)
for i := 0; i<len(split); i++ {
if (split[i] == "get" || split[i] == "delete") &&
(i+1 < length) { // next word may not exist
id, err := strconv.Atoi64(split[i+1])
return id, (err == nil)
}
}
return 0,false
}
...
// Handle a delete request of remarks
func deleteRemark(w http.ResponseWriter, r *http.Request) {
c := appengine.NewContext(r)
switch r.Method {
case DELETE:
c.Infof("Deleteing Remark\n")
c.Infof("Requested URL: %s\n", r.RawURL)
c.Infof("Requested URL path: %s\n", r.URL.Path)
// Check if we were requested for a specific remark
id, foundID := getRemarkID(r.URL.Path)
if !foundID {
msg := "Specified remark does not exist\n"
c.Infof(msg)
http.Error(w, msg, http.StatusNotFound)
return
} else { // foun ID within URL
query := datastore.NewQuery(REMARK_KIND).Filter("Time=", id)
// check if any results exist
count, err := query.Count(c)
if err != nil {
http.Error(w, err.String(), http.StatusInternalServerError)
return
}
if count == 0 {
msg := "Specified remark does not exist\n"
c.Infof(msg)
http.Error(w, msg, http.StatusNotFound)
return
}
// remove remark with given ID
itr := query.Run(c)
for {
var remark Remark
key, err := itr.Next(&remark)
if err == datastore.Done {
break
} else if err != nil {
http.Error(w, err.String(), http.StatusInternalServerError)
return
}
c.Infof("Removing id:%d remark:%s", key.IntID(), remark.Content)
datastore.Delete(c, key)
}
}
default:
msg := "Invalid request\n"
c.Infof(msg)
http.Error(w, msg, http.StatusBadRequest)
}
}
...
getと違うのはIDが指定されなかったらエラーを返す点と、クエリーの結果見つかったkeyに対してdatastore.Deleteを呼んで、keyを消してる点くらい。
クライアントサイド
クライアントサイドもやっぱりgetと限りなく似ていて、DELETEは若干マイナーなのか、GETみたいな便利なAPIが無いからhttp.Requestを自分で作ってからhttp.Client.Doを呼ぶ一手間が増えたくらい。
package main
import (
"http"
"fmt"
"os"
)
func main() {
client := new(http.Client)
remarkUrlRoot := "http://localhost:8080/1/remark/"
deleteUrl := remarkUrlRoot + "delete/1312292876000000"
request, err := http.NewRequest("DELETE", deleteUrl, nil)
if err != nil {
fmt.Printf("Error: %s",err)
return
}
r, err := client.Do(request)
if err != nil {
fmt.Printf("Error: %s",err)
return
}
fmt.Println(r.Status)
bufSize := 256
buf := make([]byte, bufSize)
for {
read, err := r.Body.Read(buf)
if read == 0 && err == os.EOF {
fmt.Println("Finished reading")
break
} else if err != nil {
fmt.Printf("Error during read: %s",err)
break
}
// convert the buffer to a string and print it
fmt.Println(string(buf[0:read]))
}
r.Body.Close()
}
サーバーサイドの出力
INFO 2011-08-02 13:55:43,693 __init__.py:347] building _go_app INFO 2011-08-02 13:55:44,656 __init__.py:333] running _go_app 2011/08/02 13:55:44 INFO: Deleteing Remark 2011/08/02 13:55:44 INFO: Requested URL: /1/remark/delete/1312292876000000 2011/08/02 13:55:44 INFO: Requested URL path: /1/remark/delete/1312292876000000 2011/08/02 13:55:44 INFO: Removing id:1312292876 remark:aardvark INFO 2011-08-02 13:55:44,771 dev_appserver.py:4248] "DELETE /1/remark/delete/1312292876000000 HTTP/1.1" 200 -
クライアントサイドの出力
$ ./client 200 OK Finished reading
次回
次回はPUT。それでこの連載は一旦終わりかなー。
(続く)
0 件のコメント:
コメントを投稿