diff options
Diffstat (limited to 'vendor/github.com/zenazn/goji/example/main.go')
| -rw-r--r-- | vendor/github.com/zenazn/goji/example/main.go | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/vendor/github.com/zenazn/goji/example/main.go b/vendor/github.com/zenazn/goji/example/main.go new file mode 100644 index 0000000..b2bcf6f --- /dev/null +++ b/vendor/github.com/zenazn/goji/example/main.go @@ -0,0 +1,177 @@ +// Command example is a sample application built with Goji. Its goal is to give +// you a taste for what Goji looks like in the real world by artificially using +// all of its features. +// +// In particular, this is a complete working site for gritter.com, a site where +// users can post 140-character "greets". Any resemblance to real websites, +// alive or dead, is purely coincidental. +package main + +import ( + "fmt" + "io" + "net/http" + "regexp" + "strconv" + "time" + + "github.com/goji/param" + "github.com/zenazn/goji" + "github.com/zenazn/goji/web" + "github.com/zenazn/goji/web/middleware" +) + +// Note: the code below cuts a lot of corners to make the example app simple. + +func main() { + // Add routes to the global handler + goji.Get("/", Root) + // Fully backwards compatible with net/http's Handlers + goji.Get("/greets", http.RedirectHandler("/", 301)) + // Use your favorite HTTP verbs + goji.Post("/greets", NewGreet) + // Use Sinatra-style patterns in your URLs + goji.Get("/users/:name", GetUser) + // Goji also supports regular expressions with named capture groups. + goji.Get(regexp.MustCompile(`^/greets/(?P<id>\d+)$`), GetGreet) + + // Middleware can be used to inject behavior into your app. The + // middleware for this application are defined in middleware.go, but you + // can put them wherever you like. + goji.Use(PlainText) + + // If the patterns ends with "/*", the path is treated as a prefix, and + // can be used to implement sub-routes. + admin := web.New() + goji.Handle("/admin/*", admin) + + // The standard SubRouter middleware helps make writing sub-routers + // easy. Ordinarily, Goji does not manipulate the request's URL.Path, + // meaning you'd have to repeat "/admin/" in each of the following + // routes. This middleware allows you to cut down on the repetition by + // eliminating the shared, already-matched prefix. + admin.Use(middleware.SubRouter) + // You can also easily attach extra middleware to sub-routers that are + // not present on the parent router. This one, for instance, presents a + // password prompt to users of the admin endpoints. + admin.Use(SuperSecure) + + admin.Get("/", AdminRoot) + admin.Get("/finances", AdminFinances) + + // Goji's routing, like Sinatra's, is exact: no effort is made to + // normalize trailing slashes. + goji.Get("/admin", http.RedirectHandler("/admin/", 301)) + + // Use a custom 404 handler + goji.NotFound(NotFound) + + // Sometimes requests take a long time. + goji.Get("/waitforit", WaitForIt) + + // Call Serve() at the bottom of your main() function, and it'll take + // care of everything else for you, including binding to a socket (with + // automatic support for systemd and Einhorn) and supporting graceful + // shutdown on SIGINT. Serve() is appropriate for both development and + // production. + goji.Serve() +} + +// Root route (GET "/"). Print a list of greets. +func Root(w http.ResponseWriter, r *http.Request) { + // In the real world you'd probably use a template or something. + io.WriteString(w, "Gritter\n======\n\n") + for i := len(Greets) - 1; i >= 0; i-- { + Greets[i].Write(w) + } +} + +// NewGreet creates a new greet (POST "/greets"). Creates a greet and redirects +// you to the created greet. +// +// To post a new greet, try this at a shell: +// $ now=$(date +'%Y-%m-%dT%H:%M:%SZ') +// $ curl -i -d "user=carl&message=Hello+World&time=$now" localhost:8000/greets +func NewGreet(w http.ResponseWriter, r *http.Request) { + var greet Greet + + // Parse the POST body into the Greet struct. The format is the same as + // is emitted by (e.g.) jQuery.param. + r.ParseForm() + err := param.Parse(r.Form, &greet) + + if err != nil || len(greet.Message) > 140 { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + + // We make no effort to prevent races against other insertions. + Greets = append(Greets, greet) + url := fmt.Sprintf("/greets/%d", len(Greets)-1) + http.Redirect(w, r, url, http.StatusCreated) +} + +// GetUser finds a given user and her greets (GET "/user/:name") +func GetUser(c web.C, w http.ResponseWriter, r *http.Request) { + io.WriteString(w, "Gritter\n======\n\n") + handle := c.URLParams["name"] + user, ok := Users[handle] + if !ok { + http.Error(w, http.StatusText(404), 404) + return + } + + user.Write(w, handle) + + io.WriteString(w, "\nGreets:\n") + for i := len(Greets) - 1; i >= 0; i-- { + if Greets[i].User == handle { + Greets[i].Write(w) + } + } +} + +// GetGreet finds a particular greet by ID (GET "/greets/\d+"). Does no bounds +// checking, so will probably panic. +func GetGreet(c web.C, w http.ResponseWriter, r *http.Request) { + id, err := strconv.Atoi(c.URLParams["id"]) + if err != nil { + http.Error(w, http.StatusText(404), 404) + return + } + // This will panic if id is too big. Try it out! + greet := Greets[id] + + io.WriteString(w, "Gritter\n======\n\n") + greet.Write(w) +} + +// WaitForIt is a particularly slow handler (GET "/waitforit"). Try loading this +// endpoint and initiating a graceful shutdown (Ctrl-C) or Einhorn reload. The +// old server will stop accepting new connections and will attempt to kill +// outstanding idle (keep-alive) connections, but will patiently stick around +// for this endpoint to finish. How kind of it! +func WaitForIt(w http.ResponseWriter, r *http.Request) { + io.WriteString(w, "This is going to be legend... (wait for it)\n") + if fl, ok := w.(http.Flusher); ok { + fl.Flush() + } + time.Sleep(15 * time.Second) + io.WriteString(w, "...dary! Legendary!\n") +} + +// AdminRoot is root (GET "/admin/root"). Much secret. Very administrate. Wow. +func AdminRoot(w http.ResponseWriter, r *http.Request) { + io.WriteString(w, "Gritter\n======\n\nSuper secret admin page!\n") +} + +// AdminFinances would answer the question 'How are we doing?' +// (GET "/admin/finances") +func AdminFinances(w http.ResponseWriter, r *http.Request) { + io.WriteString(w, "Gritter\n======\n\nWe're broke! :(\n") +} + +// NotFound is a 404 handler. +func NotFound(w http.ResponseWriter, r *http.Request) { + http.Error(w, "Umm... have you tried turning it off and on again?", 404) +} |
