This repository has been archived by the owner on Nov 28, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
hello.go
executable file
·95 lines (86 loc) · 2.73 KB
/
hello.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package guestbook
import (
"html/template"
"net/http"
"time"
"golang.org/x/net/context"
"google.golang.org/appengine"
"google.golang.org/appengine/datastore"
"google.golang.org/appengine/user"
)
type Greeting struct {
Author string
Content string
Date time.Time
}
func init() {
http.HandleFunc("/", root)
http.HandleFunc("/sign", sign)
}
// IMPORTANT
// you might need to run this at the terminal
// go get -u golang.org/x/net/context
// guestbookKey returns the key used for all guestbook entries.
func guestbookKey(c context.Context) *datastore.Key {
// The string "default_guestbook" here could be varied to have multiple guestbooks.
return datastore.NewKey(c, "Guestbook", "default_guestbook", 0, nil)
}
func root(res http.ResponseWriter, req *http.Request) {
c := appengine.NewContext(req)
// Ancestor queries, as shown here, are strongly consistent with the High
// Replication Datastore. Queries that span entity groups are eventually
// consistent. If we omitted the .Ancestor from this query there would be
// a slight chance that Greeting that had just been written would not
// show up in a query.
q := datastore.NewQuery("Greeting").Ancestor(guestbookKey(c)).Order("-Date").Limit(10)
greetings := make([]Greeting, 0, 10)
if _, err := q.GetAll(c, &greetings); err != nil {
http.Error(res, err.Error(), http.StatusInternalServerError)
return
}
if err := guestbookTemplate.Execute(res, greetings); err != nil {
http.Error(res, err.Error(), http.StatusInternalServerError)
}
}
var guestbookTemplate = template.Must(template.New("book").Parse(`
<html>
<head>
<title>Go Guestbook</title>
</head>
<body>
{{range .}}
{{with .Author}}
<p><b>{{.}}</b> wrote:</p>
{{else}}
<p>An anonymous person wrote:</p>
{{end}}
<pre>{{.Content}}</pre>
{{end}}
<form action="/sign" method="POST">
<div><textarea name="content" rows="3" cols="60"></textarea></div>
<div><input type="submit" value="Sign Guestbook"></div>
</form>
</body>
</html>
`))
func sign(res http.ResponseWriter, req *http.Request) {
c := appengine.NewContext(req)
g := Greeting{
Content: req.FormValue("content"),
Date: time.Now(),
}
if u := user.Current(c); u != nil {
g.Author = u.String()
}
// We set the same parent key on every Greeting entity to ensure each Greeting
// is in the same entity group. Queries across the single entity group
// will be consistent. However, the write rate to a single entity group
// should be limited to ~1/second.
key := datastore.NewIncompleteKey(c, "Greeting", guestbookKey(c))
_, err := datastore.Put(c, key, &g)
if err != nil {
http.Error(res, err.Error(), http.StatusInternalServerError)
return
}
http.Redirect(res, req, "/", http.StatusFound)
}