novelty.go

Single word (yes/no) site for app engine in go
git clone https://wehaveforgeathome.hates.computer/novelty.go.git
Log | Files | Refs | LICENSE

commit ab6bb56cd0f3bb62b67fe91782a2210e931643e7
Author: Ryan Wolf <rwolf@borderstylo.com>
Date:   Mon, 26 Mar 2012 00:05:49 -0700

initial commit

Diffstat:
A.gitignore | 1+
ALICENSE | 11+++++++++++
ATODO | 8++++++++
Aapp.yaml.example | 8++++++++
Aindex.template | 8++++++++
Anovelty/novelty.go | 72++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 108 insertions(+), 0 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1 @@ +app.yaml diff --git a/LICENSE b/LICENSE @@ -0,0 +1,11 @@ + Tumbolia Public License + +Copyright 2012, Ryan Wolf <rwolf.webdev@gmail.com> + +Copying and distribution of this file, with or without modification, are +permitted in any medium without royalty provided the copyright notice and this +notice are preserved. + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. opan saurce LOL diff --git a/TODO b/TODO @@ -0,0 +1,8 @@ +* readme +* use post instead of get for editing +* basic auth for editing +* backend replication to survive instance restarts +* styling for index.template +* make sure we're sending right content types +* html error pages +* env variables for question, basic auth header diff --git a/app.yaml.example b/app.yaml.example @@ -0,0 +1,8 @@ +application: novelty +version: 1 +runtime: go +api_version: 3 + +handlers: +- url: /.* + script: _go_app diff --git a/index.template b/index.template @@ -0,0 +1,8 @@ +<html> + <head> + <title>{{html .Question}}</title> + </head> + <body> + <h1>{{html .Answer}}</h1> + </body> +</html> diff --git a/novelty/novelty.go b/novelty/novelty.go @@ -0,0 +1,72 @@ +package hello + +import ( + "http" + "strings" + "template" +) + +var question = "Is Ryan at the Office?" +var answer = "yes" +var rootTemplate = template.Must(template.New("").ParseFile("index.template")) + +type Context struct{ + Question string + Answer string +} + +type RequestHandler func(w http.ResponseWriter, r *http.Request) + +var routes = make(map[string]map[string]RequestHandler) + +func addRoute(path string, method string, handler RequestHandler) { + if routes[path] == nil { + routes[path] = make(map[string]RequestHandler) + } + routes[path][method] = handler +} + +func router(w http.ResponseWriter, r *http.Request) { + route := routes[r.URL.Path] + if route == nil { + http.Error(w, "Not Found", http.StatusNotFound) + return + } + handler := route[r.Method] + if handler == nil { + //TODO: Is there a cleaner way to get a comma-seperated list of keys? + methods := make([]string, len(route)) + i := 0 + for m, _ := range route { + methods[i] = m + i++ + } + w.Header().Set("Allow", strings.Join(methods, ",")) + http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed) + return + } + handler(w, r) +} + +func init() { + addRoute("/", "GET", func(w http.ResponseWriter, r *http.Request) { + // TODO: Is there a way to skip the type and use an inline struct? + context := Context{ Question: question, Answer: answer } + err := rootTemplate.Execute(w, context) + if err != nil { + http.Error(w, err.String(), http.StatusInternalServerError) + } + }) + + addRoute("/yes", "GET", func(w http.ResponseWriter, r *http.Request) { + answer = "yes" + http.Redirect(w, r, "", http.StatusFound) + }) + + addRoute("/no", "GET", func(w http.ResponseWriter, r *http.Request) { + answer = "no" + http.Redirect(w, r, "", http.StatusFound) + }) + + http.HandleFunc("/", router) +}