// PUT http://localhost:8080/profiles/ahdkZXZ-ZmVkZXJhdGlvbi1zZXJ2aWNlc3IVCxIIcHJvZmlsZXMYgICAgICAgAoM // {"first_name": "Ivan", "nick_name": "Socks", "last_name": "Hawkes"} // func (u *ProfileApi) update(r *restful.Request, w *restful.Response) { c := appengine.NewContext(r.Request) // Decode the request parameter to determine the key for the entity. k, err := datastore.DecodeKey(r.PathParameter("profile-id")) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } // Marshall the entity from the request into a struct. p := new(Profile) err = r.ReadEntity(&p) if err != nil { w.WriteError(http.StatusNotAcceptable, err) return } // Retrieve the old entity from the datastore. old := Profile{} if err := datastore.Get(c, k, &old); err != nil { if err.Error() == "datastore: no such entity" { http.Error(w, err.Error(), http.StatusNotFound) } else { http.Error(w, err.Error(), http.StatusInternalServerError) } return } // Check we own the profile before allowing them to update it. // Optionally, return a 404 instead to help prevent guessing ids. // TODO: Allow admins access. if old.Email != user.Current(c).String() { http.Error(w, "You do not have access to this resource", http.StatusForbidden) return } // Since the whole entity is re-written, we need to assign any invariant fields again // e.g. the owner of the entity. p.Email = user.Current(c).String() // Keep track of the last modification date. p.LastModified = time.Now() // Attempt to overwrite the old entity. _, err = datastore.Put(c, k, p) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } // Let them know it succeeded. w.WriteHeader(http.StatusNoContent) }
// GET http://localhost:8080/profiles/ahdkZXZ-ZmVkZXJhdGlvbi1zZXJ2aWNlc3IVCxIIcHJvZmlsZXMYgICAgICAgAoM // func (u ProfileApi) read(r *restful.Request, w *restful.Response) { c := appengine.NewContext(r.Request) // Decode the request parameter to determine the key for the entity. k, err := datastore.DecodeKey(r.PathParameter("profile-id")) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } // Retrieve the entity from the datastore. p := Profile{} if err := datastore.Get(c, k, &p); err != nil { if err.Error() == "datastore: no such entity" { http.Error(w, err.Error(), http.StatusNotFound) } else { http.Error(w, err.Error(), http.StatusInternalServerError) } return } // Check we own the profile before allowing them to view it. // Optionally, return a 404 instead to help prevent guessing ids. // TODO: Allow admins access. if p.Email != user.Current(c).String() { http.Error(w, "You do not have access to this resource", http.StatusForbidden) return } w.WriteEntity(p) }
// POST http://localhost:8080/profiles // {"first_name": "Ivan", "nick_name": "Socks", "last_name": "Hawkes"} // func (u *ProfileApi) insert(r *restful.Request, w *restful.Response) { c := appengine.NewContext(r.Request) // Marshall the entity from the request into a struct. p := new(Profile) err := r.ReadEntity(&p) if err != nil { w.WriteError(http.StatusNotAcceptable, err) return } // Ensure we start with a sensible value for this field. p.LastModified = time.Now() // The profile belongs to this user. p.Email = user.Current(c).String() k, err := datastore.Put(c, datastore.NewIncompleteKey(c, "profiles", nil), p) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } // Let them know the location of the newly created resource. // TODO: Use a safe Url path append function. w.AddHeader("Location", u.Path+"/"+k.Encode()) // Return the resultant entity. w.WriteHeader(http.StatusCreated) w.WriteEntity(p) }