commit ab6bb56cd0f3bb62b67fe91782a2210e931643e7
Author: Ryan Wolf <rwolf@borderstylo.com>
Date: Mon, 26 Mar 2012 00:05:49 -0700
initial commit
Diffstat:
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)
+}