func transformImage(c appengine.Context, n notification) (err error) {
	id := strings.Join([]string{n.BucketName, n.ObjectName}, "/")
	client := urlfetch.Client(c)
	values := url.Values{
		"id":      {id},
		"save-to": {saveToBucketName},
	}
	postUrlParts := []string{"http://", processingPoolIp, "/process"}
	postUrl := strings.Join(postUrlParts, "")
	c.Infof("Sending request to transform: %v", n.ObjectName)
	resp, err := client.PostForm(postUrl, values)
	if err != nil {
		c.Errorf("Error sending POST to URL: %v", err)
		return
	}
	c.Infof("HTTP POST returned status: %v", resp.Status)
	if resp.StatusCode != http.StatusOK {
		err = errors.New("Non-200 response from backend")
		return
	}
	respBody, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		c.Errorf("Error attempting to read resp body: %v", err)
		return
	}
	c.Infof("respBody=%v", string(respBody))
	return
}
transformImage takes a notification to manipulate an image and asks our backend service to
compute some transformation on it via HTTP. If the service is unavailable, it returns an error.
package main
import (
	"encoding/json"
	"errors"
	"io/ioutil"
	"net/http"
	"net/url"
	"path/filepath"
	"strings"
	"appengine"
	"appengine/delay"
	"appengine/urlfetch"
)
const (
	saveToBucketName = "fifth-curve-684-output-bucket"
	processingPoolIp = "107.178.243.219"
)
var (
	transformImageFunc = delay.Func("transform", transformImage)
)
func init() {
	http.HandleFunc("/", handler)
}
type notification struct {
	ID             string `json:"id"`
	ObjectName     string `json:"name"`
	ObjectSelfLink string `json:"selfLink"`
	BucketName     string `json:"bucket"`
}
func handler(w http.ResponseWriter, r *http.Request) {
	c := appengine.NewContext(r)
	resourceState := r.Header.Get("X-Goog-Resource-State")
	c.Infof("Cloud Storage Notification: %v", resourceState)
	if resourceState != "exists" {
		return
	}
	b, err := ioutil.ReadAll(r.Body)
	if err != nil {
		c.Errorf("Error attempting to read req body: %v", err)
		return
	}
	c.Infof("request: %v", string(b))
	n := &notification{}
	if err := json.Unmarshal(b, n); err != nil {
		c.Errorf("Error unmarshalling JSON: %v", err)
		return
	}
	c.Infof("%s: %s", n.ID, n.BucketName, n.ObjectName)
	n.ObjectName, err = url.QueryUnescape(filepath.Base(n.ObjectSelfLink))
	if err != nil {
		c.Errorf("Error attempting to build object name from self link %v: %v",
			n.ObjectSelfLink, err)
		return
	}
	transformImageFunc.Call(c, *n)
}