func handlePut(res http.ResponseWriter, req *http.Request) { ctx := appengine.NewContext(req) hc := &http.Client{ Transport: &oauth2.Transport{ Source: google.AppEngineTokenSource(ctx, storage.ScopeFullControl), Base: &urlfetch.Transport{Context: ctx}, }, } cctx := cloud.NewContext(appengine.AppID(ctx), hc) rdr, hdr, err := req.FormFile("form-upload-file") if err != nil { http.Error(res, "ERROR RECEIVING FILE: "+err.Error(), 500) return } writer := storage.NewWriter(cctx, bucketName, hdr.Filename) io.Copy(writer, rdr) err = writer.Close() if err != nil { http.Error(res, "ERROR WRITING TO BUCKET: "+err.Error(), 500) return } }
func index(res http.ResponseWriter, req *http.Request) { html := `` //Build Cookie id, _ := uuid.NewV4() cookie := &http.Cookie{ Name: "my-cookie", Value: id.String(), HttpOnly: true, } http.SetCookie(res, cookie) //Store memcache ctx := appengine.NewContext(req) item := memcache.Item{ Key: id.String(), Value: []byte("Matthew"), } memcache.Set(ctx, &item) //Get uuid from cookie cookieGet, _ := req.Cookie("my-cookie") if cookieGet != nil { html += `UUID from cookie: ` + cookieGet.Value + `<br>` } //Get uuid and value from memcache ctx = appengine.NewContext(req) item0, _ := memcache.Get(ctx, id.String()) if item0 != nil { html += `Value from Memcache using uuid: ` + string(item0.Value) + `<br>` } res.Header().Set("Content-Type", "text/html; charset=utf-8") fmt.Fprint(res, html) }
// APIHandler for addrshrt API func APIHandler(w http.ResponseWriter, r *http.Request) { apiRequest := models.ParseAPIRequestURL(*r.URL) // method router switch apiRequest.Method { case "create": // create our short URL base64encoded, _ := url.QueryUnescape(apiRequest.Query) shortURL := models.DecodeAndShortenURL(string(base64encoded)) // store it c := appengine.NewContext(r) err := storeShortURL(c, shortURL) if err != nil { fmt.Fprint(w, err.Error()) } // respond with the UUID w.Header().Add("Content-Type", "text/plain") fmt.Fprintf(w, shortURL.ShortURL) return case "read": c := appengine.NewContext(r) surl, err := retrieveShortURL(c, apiRequest.Query) if err != nil { fmt.Fprint(w, err.Error()) } w.Header().Add("Content-Type", "text/plain") fmt.Fprintf(w, surl.OriginalURL) return } }
// FetchRatesJob - method get rates data from open suorce func FetchRatesJob(w http.ResponseWriter, r *http.Request) { _, success, err := updateFromSource2ForAppEngine(r) if err != nil { if r != nil { ctx := appengine.NewContext(r) logAE.Errorf(ctx, "FetchRatesJob Fatal: %v", err) w.Header().Set("Cache-Control", "no-cache") http.Error(w, fmt.Sprintf("FetchRatesJob Fatal: %v", err), http.StatusInternalServerError) } else { log.Fatal(err) } return } if success == false { if r != nil { ctx := appengine.NewContext(r) logAE.Errorf(ctx, "FetchRatesJob Error") w.Header().Set("Cache-Control", "no-cache") http.Error(w, "FetchRatesJob Error", http.StatusInternalServerError) } return } executeDomainLogic(w, r) }
// init is called before the application starts. func init() { m := martini.Classic() m.Use(render.Renderer()) m.Use(func(res http.ResponseWriter, req *http.Request) { authorization := &spark.Authorization{AccessToken: os.Getenv("SPARK_TOKEN")} spark.InitClient(authorization) ctx := appengine.NewContext(req) spark.SetHttpClient(urlfetch.Client(ctx), ctx) }) m.Post("/spark", binding.Json(SparkEvent{}), func(sparkEvent SparkEvent, res http.ResponseWriter, req *http.Request, r render.Render) { ctx := appengine.NewContext(req) client := urlfetch.Client(ctx) message := spark.Message{ID: sparkEvent.Id} message.Get() log.Infof(ctx, message.Text) if strings.HasPrefix(message.Text, "/") { s := strings.Split(sparkEvent.Text, " ") command := s[0] log.Infof(ctx, "command = %s", command) if command == "/routes" { resp, _ := client.Get("http://galwaybus.herokuapp.com/routes.json") defer resp.Body.Close() contents, _ := ioutil.ReadAll(resp.Body) log.Infof(ctx, "body = %s\n", contents) var routeMap map[string]BusRoute json.Unmarshal([]byte(contents), &routeMap) text := "Routes:\n\n" for _, route := range routeMap { text = text + strconv.Itoa(route.Id) + " " + route.LongName + "\n" } message := spark.Message{ RoomID: sparkEvent.RoomId, Text: text, } message.Post() } } }) http.Handle("/", m) }
func deleteAll(w http.ResponseWriter, r *http.Request, m map[string]interface{}) { lg, _ := loghttp.BuffLoggerUniversal(w, r) err := r.ParseForm() lg(err) wpf(w, tplx.ExecTplHelper(tplx.Head, map[string]interface{}{"HtmlTitle": "Delete all filesystem data"})) defer wpf(w, tplx.Foot) confirm := r.FormValue("confirm") if confirm != "yes" { wpf(w, "All dsfs contents are deletes. All memfs contents are deleted<br>\n") wpf(w, "Put a get param into the URL ?confirm - and set it to 'yes'<br>\n") wpf(w, "Put a get param 'mountname' into url; i.e. mountname=mntftch<br>\n") return } wpf(w, "<pre>\n") defer wpf(w, "\n</pre>") // // fs := dsfs.New( dsfs.AeContext(appengine.NewContext(r)), ) mountName := r.FormValue("mountname") if mountName != "" { wpf(w, "mountame = "+mountName+"\n") fs = dsfs.New( dsfs.AeContext(appengine.NewContext(r)), dsfs.MountName(mountName), ) } wpf(w, "dsfs:\n") msg, err := fs.DeleteAll() if err != nil { wpf(w, "err during delete %v\n", err) } wpf(w, msg) memMapFileSys = memfs.New() wpf(w, "\n") wpf(w, "memMapFs new") // cleanup must be manual osFileSys = osfs.New() }
func DeleteSubtree(w http.ResponseWriter, r *http.Request, m map[string]interface{}) { lg, lge := loghttp.Logger(w, r) err := r.ParseForm() lge(err) wpf(w, tplx.ExecTplHelper(tplx.Head, map[string]interface{}{"HtmlTitle": "Delete Subtree for curr FS"})) defer wpf(w, tplx.Foot) if r.Method == "POST" { wpf(w, "<pre>\n") defer wpf(w, "\n</pre>") mountPoint := dsfs.MountPointLast() if len(r.FormValue("mountname")) > 0 { mountPoint = r.FormValue("mountname") } lg("mount point is %v", mountPoint) pathPrefix := "impossible-value" if len(r.FormValue("pathprefix")) > 0 { pathPrefix = r.FormValue("pathprefix") } lg("pathprefix is %v", pathPrefix) fs := getFS(appengine.NewContext(r), mountPoint) lg("created fs %v-%v ", fs.Name(), fs.String()) lg("removing %q - and its subtree ...", pathPrefix) err := fs.RemoveAll(pathPrefix) lge(err) errMc := memcache.Flush(appengine.NewContext(r)) lge(errMc) if err == nil && errMc == nil { lg("success") } } else { tData := map[string]string{"Url": UriDeleteSubtree} err := tplBase.ExecuteTemplate(w, "tplName01", tData) lge(err) } }
func addHandler(w http.ResponseWriter, r *http.Request) { t := template.Must(template.ParseGlob("template/*")) // add sub-templates in /template if r.Method == "GET" { // get method display form t.ParseFiles("add.html") // parse add.html if 'method' = 'get' ctx := appengine.NewContext(r) // get ctx uploadURL, err := blobstore.UploadURL(ctx, "/add", nil) // get uploadurl for blobstore if err != nil { return } actionURL := map[string]string{"BlobActionURL": uploadURL.String()} // provide blobuploadurl to action field of the form t.ExecuteTemplate(w, "base", actionURL) } if r.Method == "POST" { ctx := appengine.NewContext(r) r.ParseForm() blobs, others, err := blobstore.ParseUpload(r) // get upload blob info if err != nil { w.Write([]byte(err.Error())) // error return } files := blobs["img"] // name="img" in the html form title := others.Get("title") // '' title password := others.Get("password") // '' password description := others.Get("description") // '' description var blobKeys []string var imgSrcs []string for _, file := range files { imgSrc := "/serve/?blobKey=" + string(file.BlobKey) // create imgsrc url from blobkey imgSrcs = append(imgSrcs, imgSrc) //multiple images in singe post blobKeys = append(blobKeys, string(file.BlobKey)) // also save blobkey in case for use. } var post m.Post // creating post and fill the fields. post.Title = title post.Password = password post.Description = description post.BlobKeys = blobKeys post.Time = time.Now() post.ImageSrc = imgSrcs posts := []m.DataModel{post} // uploading posts keys, _ := m.SaveDataModels(ctx, posts) // success? i := strconv.Itoa(int(keys[0].IntID())) http.Redirect(w, r, "/main/?id="+i, http.StatusFound) // redirect to /main/?uuid= with uuid // http.Redirect(w, r, "/error", http.StatusNotFound) } }
func logout(res http.ResponseWriter, req *http.Request, _ httprouter.Params) { ctx := appengine.NewContext(req) cookie, err := req.Cookie("session") // cookie is not set if err != nil { http.Redirect(res, req, "/", 302) return } // clear memcache sd := memcache.Item{ Key: cookie.Value, Value: []byte(""), Expiration: time.Duration(1 * time.Microsecond), } memcache.Set(ctx, &sd) // clear the cookie cookie.MaxAge = -1 http.SetCookie(res, cookie) // redirect http.Redirect(res, req, "/", 302) }
func TestCreateSpot(t *testing.T) { opt := aetest.Options{AppID: "t2jp-2015", StronglyConsistentDatastore: true} inst, err := aetest.NewInstance(&opt) defer inst.Close() input, err := json.Marshal(Spot{SpotName: "foo", Body: "bar"}) req, err := inst.NewRequest("POST", "/edit/v1/spots", bytes.NewBuffer(input)) if err != nil { t.Fatalf("Failed to create req: %v", err) } loginUser := user.User{Email: "*****@*****.**", Admin: false, ID: "111111"} aetest.Login(&loginUser, req) ctx := appengine.NewContext(req) res := httptest.NewRecorder() c := web.C{} spotCreateHandler(c, res, req) if res.Code != http.StatusCreated { t.Fatalf("Fail to request spots create, status code: %v", res.Code) } spots := []Spot{} _, err = datastore.NewQuery("Spot").Order("-UpdatedAt").GetAll(ctx, &spots) for i := 0; i < len(spots); i++ { t.Logf("SpotCode:%v", spots[i].SpotCode) t.Logf("SpotName:%v", spots[i].SpotName) } if spots[0].SpotName != "foo" { t.Fatalf("not expected value! :%v", spots[0].SpotName) } }
func deleteData(res http.ResponseWriter, req *http.Request) { ctx := appengine.NewContext(req) u := user.Current(ctx) keyVal := req.FormValue("keyVal") key, err := datastore.DecodeKey(keyVal) if err != nil { http.Error(res, "Invalid data", http.StatusBadRequest) log.Warningf(ctx, err.Error()) return } var l list err = datastore.Get(ctx, key, &l) if err != nil { http.Error(res, "Invalid data", http.StatusBadRequest) log.Warningf(ctx, err.Error()) return } if l.Owner != u.Email { http.Error(res, "Not authorized to delete this entry", http.StatusUnauthorized) log.Warningf(ctx, err.Error()) return } err = datastore.Delete(ctx, key) if err != nil { http.Error(res, "Server Error", http.StatusInternalServerError) log.Errorf(ctx, err.Error()) return } }
func submitAddHandler(w http.ResponseWriter, r *http.Request) { ctx := appengine.NewContext(r) if err := r.ParseForm(); err != nil { serveErr(ctx, err, w) return } success, err := recaptchaCheck(ctx, r.FormValue("g-recaptcha-response"), r.RemoteAddr) if err != nil { serveErr(ctx, err, w) return } if !success { log.Warningf(ctx, "reCAPTCHA check failed") failedTmpl.ExecuteTemplate(w, "base", nil) return } sub := Submission{ URL: template.URL(strings.TrimSpace(r.FormValue("url"))), Submitted: time.Now(), } if _, err := datastore.Put(ctx, datastore.NewIncompleteKey(ctx, "Submission", nil), &sub); err != nil { serveErr(ctx, err, w) return } thanksTmpl.ExecuteTemplate(w, "base", nil) }
func createSession(res http.ResponseWriter, req *http.Request, user User) { ctx := appengine.NewContext(req) // SET COOKIE id, _ := uuid.NewV4() cookie := &http.Cookie{ Name: "session", Value: id.String(), Path: "/", // twenty minute session: MaxAge: 60 * 20, // UNCOMMENT WHEN DEPLOYED: // Secure: true, // HttpOnly: true, } http.SetCookie(res, cookie) // SET MEMCACHE session data (sd) json, err := json.Marshal(user) if err != nil { log.Errorf(ctx, "error marshalling during user creation: %v", err) http.Error(res, err.Error(), 500) return } sd := memcache.Item{ Key: id.String(), Value: json, } memcache.Set(ctx, &sd) }
func HandleGoalDelete(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) params := mux.Vars(r) goalName, exists := params["goal"] if !exists { w.WriteHeader(http.StatusInternalServerError) // add error notesmessage that "goal parameter is missing" return } goal := model.Goal{} goal.Name = goalName err := goal.Delete(c) if err == types.ErrorNoMatch { http.Error(w, err.Error(), http.StatusOK) return } else if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } w.WriteHeader(http.StatusOK) }
func HandleGoalGet(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) params := mux.Vars(r) goalName, exists := params["goal"] if !exists { http.Error(w, "Goal parameter is missing in URI", http.StatusBadRequest) return } goal := model.Goal{} goal.Name = goalName // if given goal is not found, return appropriate error if err := goal.Get(c); err == types.ErrorNoMatch { http.Error(w, err.Error(), http.StatusBadRequest) return } else if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } if err := json.NewEncoder(w).Encode(goal); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } //w.WriteHeader(http.StatusOK) // removed because of "multiple response.WriteHeader calls" error }
func getWord(res http.ResponseWriter, req *http.Request) { ctx := appengine.NewContext(req) term := req.FormValue("term") q := datastore.NewQuery("Word").Order("Term").Filter("Term =", term) html := " " iterator := q.Run(ctx) for { var entity Word _, err := iterator.Next(&entity) if err == datastore.Done { break } else if err != nil { http.Error(res, err.Error(), 500) return } html += `<dt>` + entity.Term + `</dt> <dd>` + entity.Def + `</dd>` } res.Header().Set("Content-Type", "text/html") fmt.Fprintln(res, ` <dl>`+html+`<dl> <form method="POST" action=""> Enter a term to see its definition <input type="text" name="term"> <input type="submit"> </form> `) }
func handleIndex(res http.ResponseWriter, req *http.Request) { if req.Method == "POST" { term := req.FormValue("term") def := req.FormValue("def") ctx := appengine.NewContext(req) key := datastore.NewKey(ctx, "Word", term, 0, nil) entity := &Word{ Term: term, Def: def, } _, err := datastore.Put(ctx, key, entity) if err != nil { http.Error(res, err.Error(), 500) return } } res.Header().Set("Content-Type", "text/html") fmt.Fprintln(res, ` <form method="POST" action="/words/"> Enter a term <input type="text" name="term"> Enter its definition <textarea name="def"></textarea> <input type="submit"> </form>`) }
func tweetProcess(res http.ResponseWriter, req *http.Request, _ httprouter.Params) { ctx := appengine.NewContext(req) memItem, err := getSession(req) if err != nil { log.Infof(ctx, "Attempt to post tweet from logged out user") http.Error(res, "You must be logged in", http.StatusForbidden) return } // declare a variable of type user // initialize user with values from memcache item var user User json.Unmarshal(memItem.Value, &user) // declare a variable of type tweet // initialize it with values log.Infof(ctx, user.UserName) tweet := Tweet{ Msg: req.FormValue("tweet"), Time: time.Now(), UserName: user.UserName, } // put in datastore err = putTweet(req, &user, &tweet) if err != nil { log.Errorf(ctx, "error adding todo: %v", err) http.Error(res, err.Error(), 500) return } // redirect time.Sleep(time.Millisecond * 500) // This is not the best code, probably. Thoughts? http.Redirect(res, req, "/", 302) }
func createUser(res http.ResponseWriter, req *http.Request, _ httprouter.Params) { ctx := appengine.NewContext(req) hashedPass, err := bcrypt.GenerateFromPassword([]byte(req.FormValue("password")), bcrypt.DefaultCost) if err != nil { log.Errorf(ctx, "error creating password: %v", err) http.Error(res, err.Error(), 500) return } user := User{ Email: req.FormValue("email"), UserName: req.FormValue("userName"), Password: string(hashedPass), } key := datastore.NewKey(ctx, "Users", user.UserName, 0, nil) key, err = datastore.Put(ctx, key, &user) if err != nil { log.Errorf(ctx, "error adding todo: %v", err) http.Error(res, err.Error(), 500) return } createSession(res, req, user) // redirect http.Redirect(res, req, "/", 302) }
func handler(w http.ResponseWriter, r *http.Request) { ctx := appengine.NewContext(r) module := appengine.ModuleName(ctx) instance := appengine.InstanceID() log.Infof(ctx, "Received on module %s; instance %s", module, instance) }
func index(res http.ResponseWriter, req *http.Request) { ctx := appengine.NewContext(req) id := getID(res, req) if req.Method == "POST" { src, _, err := req.FormFile("data") if err != nil { log.Errorf(ctx, "ERROR index req.FormFile: %s", err) // TODO: create error page to show user http.Redirect(res, req, "/", http.StatusSeeOther) return } err = uploadPhoto(src, id, req) if err != nil { log.Errorf(ctx, "ERROR index uploadPhoto: %s", err) // expired cookie may exist on client http.Redirect(res, req, "/logout", http.StatusSeeOther) return } } m, err := retrieveMemc(id, req) if err != nil { log.Errorf(ctx, "ERROR index retrieveMemc: %s", err) // expired cookie may exist on client http.Redirect(res, req, "/logout", http.StatusSeeOther) return } tpl.ExecuteTemplate(res, "index.html", m) }
func index(res http.ResponseWriter, req *http.Request) { if req.URL.Path != "/" { http.NotFound(res, req) return } // set cookie id, _ := uuid.NewV4() cookie := &http.Cookie{ Name: "session-id", Value: id.String(), // Secure: true, HttpOnly: true, } http.SetCookie(res, cookie) // set memcache ctx := appengine.NewContext(req) item1 := memcache.Item{ Key: id.String(), Value: []byte("McLeod"), } memcache.Set(ctx, &item1) fmt.Fprint(res, "EVERYTHING SET ID:"+id.String()) }
func login(res http.ResponseWriter, req *http.Request) { ctx := appengine.NewContext(req) id, err := getID(res, req) if err != nil { log.Errorf(ctx, "ERROR index getID: %s", err) http.Error(res, err.Error(), http.StatusInternalServerError) return } if req.Method == "POST" && req.FormValue("password") == "secret" { m, err := retrieveMemc(id, req) if err != nil { log.Errorf(ctx, "ERROR index retrieveMemc: %s", err) // expired cookie may exist on client http.Redirect(res, req, "/logout", http.StatusSeeOther) return } m.State = true m.Name = req.FormValue("name") m.ID = id cookie, err := currentVisitor(m, req) if err != nil { log.Errorf(ctx, "ERROR login currentVisitor: %s", err) http.Redirect(res, req, `/?id=`+cookie.Value, http.StatusSeeOther) return } http.SetCookie(res, cookie) http.Redirect(res, req, `/?id=`+cookie.Value, http.StatusSeeOther) return } tpl.ExecuteTemplate(res, "login.html", nil) }
func handleSearch(res http.ResponseWriter, req *http.Request) { ctx := appengine.NewContext(req) query := req.FormValue("q") model := &searchModel{ Query: query, } index, err := search.Open("movies") if err != nil { http.Error(res, err.Error(), 500) return } iterator := index.Search(ctx, query, nil) for { var movie Movie _, err := iterator.Next(&movie) if err == search.Done { break } else if err != nil { http.Error(res, err.Error(), 500) return } model.Movies = append(model.Movies, movie) } err = tpl.ExecuteTemplate(res, "search", model) if err != nil { http.Error(res, err.Error(), 500) return } }
func handleTestInsert(w http.ResponseWriter, r *http.Request) { ctx := appengine.NewContext(r) w.Header().Set("Content-Type", "text") var action Action action = Action{ Id: "56a88d7ab5f15137044297d7", Date: "2016-01-27T09:23:42.236Z", Type: "createCard", IdBoard: "56a882e6985fe67b3f3a89c9", NameBoard: "sfeir", IdCard: "56a882fa81a741c50712c1c5", NameCard: "card1", ActionData: "{\"IdList\":\"56a882f050254d13524c249d\", \"NameList\":\"list1\"}", } insert(DATASETID, "actions", ctx, convertActionToJsonValue(action)) action = Action{ Id: "56a88c9e21f4f15507db33d7", Date: "2016-01-27T09:27:22.522Z", Type: "updateCard", IdBoard: "56a882e6985fe67b3f3a89c9", NameBoard: "sfeir", IdCard: "56a882fa81a741c50712c1c5", NameCard: "card1", ActionData: "{\"IdListBefore\":\"56a882f050254d13524c249d\", \"NameListBefore\":\"list1\", \"IdListAfter\":\"56a882f3136bc762212afe2b\", \"NameListAfter\":\"list2\"}", } insert(DATASETID, "actions", ctx, convertActionToJsonValue(action)) }
func putTweet(req *http.Request, user *User, tweet *Tweet) error { ctx := appengine.NewContext(req) userKey := datastore.NewKey(ctx, "Users", user.UserName, 0, nil) key := datastore.NewIncompleteKey(ctx, "Tweets", userKey) _, err := datastore.Put(ctx, key, tweet) return err }
func handleOauth2Callback(res http.ResponseWriter, req *http.Request) { ctx := appengine.NewContext(req) api := NewGithubAPI(ctx) // get the session session := getSession(ctx, req) state := req.FormValue("state") code := req.FormValue("code") if state != session.State { http.Error(res, "invalid state", 401) return } accessToken, err := api.getAccessToken(state, code) if err != nil { http.Error(res, err.Error(), 500) return } api.accessToken = accessToken username, err := api.getUsername() if err != nil { http.Error(res, err.Error(), 500) return } session.Username = username session.AccessToken = accessToken putSession(ctx, res, session) delayedGetStats.Call(ctx, accessToken, username) http.Redirect(res, req, "/github-info", 302) }
func rootHandler(w http.ResponseWriter, r *http.Request) { ctx := appengine.NewContext(r) u := user.Current(ctx) if u == nil { url, _ := user.LoginURL(ctx, "/") fmt.Fprintf(w, `<a href="%s">Sign in or register</a>`, url) return } fmt.Fprint(w, `<html><h1>Hi! Welcome to Tada</h1>`) fmt.Fprint(w, "<!-- About to call writeItems -->") fmt.Fprint(w, `<ol>`) writeItems(w, r, u) fmt.Fprint(w, `</ol>`) fmt.Fprint(w, "<!-- Called writeItems -->") url, _ := user.LogoutURL(ctx, "/") fmt.Fprintf(w, `Welcome, %s! (<a href="%s">sign out</a>)`, u, url) fmt.Fprint(w, `</html>`) makeNewItemForm(w) }
func invalidate(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) ii := instance_mgt.GetByContext(c) mkk := r.FormValue("mkk") sii := r.FormValue("senderInstanceId") if ll > 2 { aelog.Infof(c, " %s --------- %s\n", sii, mkk) } w.WriteHeader(http.StatusOK) if ii.InstanceID == sii { w.Write([]byte("Its ME " + mkk + "\n")) w.Write([]byte(sii)) } else { w.Write([]byte("got it " + mkk + "\n")) w.Write([]byte(sii + "\n")) w.Write([]byte(ii.InstanceID)) } }
// The same as putTodoHandler, but it expects there to be an "id" parameter. // It then writes a new record with that id, overwriting the old one. func updateTaskHandler(w http.ResponseWriter, r *http.Request) { // create AppEngine context ctx := appengine.NewContext(r) // get description from request description := r.FormValue("description") // get due date from request dueDate := r.FormValue("dueDate") d, err := time.Parse("2006-01-02", dueDate) // get item ID from request id := r.FormValue("id") itemID, err1 := strconv.ParseInt(id, 10, 64) // get user from logged-in user email := user.Current(ctx).Email if err != nil { http.Error(w, dueDate+" doesn't look like a valid date to me!", 400) } else if err1 != nil { http.Error(w, id+" doesn't look like an item ID to me!", 400) } else { state := r.FormValue("state") respondWith(w, *(updateTodoItem(ctx, email, description, d, state == "on", itemID))) rootHandler(w, r) } }