github.com/timstclair/heapster@v0.20.0-alpha1/Godeps/_workspace/src/google.golang.org/appengine/demos/guestbook/guestbook.go (about)

     1  // Copyright 2011 Google Inc. All rights reserved.
     2  // Use of this source code is governed by the Apache 2.0
     3  // license that can be found in the LICENSE file.
     4  
     5  // This example only works on Managed VMs.
     6  // +build !appengine
     7  
     8  package main
     9  
    10  import (
    11  	"html/template"
    12  	"net/http"
    13  	"time"
    14  
    15  	"golang.org/x/net/context"
    16  
    17  	"google.golang.org/appengine"
    18  	"google.golang.org/appengine/datastore"
    19  	"google.golang.org/appengine/log"
    20  	"google.golang.org/appengine/user"
    21  )
    22  
    23  var initTime time.Time
    24  
    25  type Greeting struct {
    26  	Author  string
    27  	Content string
    28  	Date    time.Time
    29  }
    30  
    31  func main() {
    32  	http.HandleFunc("/", handleMainPage)
    33  	http.HandleFunc("/sign", handleSign)
    34  	appengine.Main()
    35  }
    36  
    37  // guestbookKey returns the key used for all guestbook entries.
    38  func guestbookKey(ctx context.Context) *datastore.Key {
    39  	// The string "default_guestbook" here could be varied to have multiple guestbooks.
    40  	return datastore.NewKey(ctx, "Guestbook", "default_guestbook", 0, nil)
    41  }
    42  
    43  var tpl = template.Must(template.ParseGlob("templates/*.html"))
    44  
    45  func handleMainPage(w http.ResponseWriter, r *http.Request) {
    46  	if r.Method != "GET" {
    47  		http.Error(w, "GET requests only", http.StatusMethodNotAllowed)
    48  		return
    49  	}
    50  	if r.URL.Path != "/" {
    51  		http.NotFound(w, r)
    52  		return
    53  	}
    54  
    55  	ctx := appengine.NewContext(r)
    56  	tic := time.Now()
    57  	q := datastore.NewQuery("Greeting").Ancestor(guestbookKey(ctx)).Order("-Date").Limit(10)
    58  	var gg []*Greeting
    59  	if _, err := q.GetAll(ctx, &gg); err != nil {
    60  		http.Error(w, err.Error(), http.StatusInternalServerError)
    61  		log.Errorf(ctx, "GetAll: %v", err)
    62  		return
    63  	}
    64  	log.Infof(ctx, "Datastore lookup took %s", time.Since(tic).String())
    65  	log.Infof(ctx, "Rendering %d greetings", len(gg))
    66  
    67  	var email, logout, login string
    68  	if u := user.Current(ctx); u != nil {
    69  		logout, _ = user.LogoutURL(ctx, "/")
    70  		email = u.Email
    71  	} else {
    72  		login, _ = user.LoginURL(ctx, "/")
    73  	}
    74  	data := struct {
    75  		Greetings            []*Greeting
    76  		Login, Logout, Email string
    77  	}{
    78  		Greetings: gg,
    79  		Login:     login,
    80  		Logout:    logout,
    81  		Email:     email,
    82  	}
    83  	w.Header().Set("Content-Type", "text/html; charset=utf-8")
    84  	if err := tpl.ExecuteTemplate(w, "guestbook.html", data); err != nil {
    85  		log.Errorf(ctx, "%v", err)
    86  	}
    87  }
    88  
    89  func handleSign(w http.ResponseWriter, r *http.Request) {
    90  	if r.Method != "POST" {
    91  		http.Error(w, "POST requests only", http.StatusMethodNotAllowed)
    92  		return
    93  	}
    94  	ctx := appengine.NewContext(r)
    95  	g := &Greeting{
    96  		Content: r.FormValue("content"),
    97  		Date:    time.Now(),
    98  	}
    99  	if u := user.Current(ctx); u != nil {
   100  		g.Author = u.String()
   101  	}
   102  	key := datastore.NewIncompleteKey(ctx, "Greeting", guestbookKey(ctx))
   103  	if _, err := datastore.Put(ctx, key, g); err != nil {
   104  		http.Error(w, err.Error(), http.StatusInternalServerError)
   105  		return
   106  	}
   107  	// Redirect with 303 which causes the subsequent request to use GET.
   108  	http.Redirect(w, r, "/", http.StatusSeeOther)
   109  }