| Index: appengine/cmd/milo/settings/themes.go
|
| diff --git a/appengine/cmd/milo/settings/themes.go b/appengine/cmd/milo/settings/themes.go
|
| index 9d6e0cb350db766124cf690c91dd9046ecf4ee49..621fc165df887047289ed57d7c86a0a74975b666 100644
|
| --- a/appengine/cmd/milo/settings/themes.go
|
| +++ b/appengine/cmd/milo/settings/themes.go
|
| @@ -14,21 +14,21 @@ import (
|
|
|
| "google.golang.org/appengine"
|
|
|
| "github.com/julienschmidt/httprouter"
|
| "github.com/luci/gae/service/info"
|
| "github.com/luci/luci-go/appengine/cmd/milo/miloerror"
|
| "github.com/luci/luci-go/appengine/gaeauth/server"
|
| "github.com/luci/luci-go/appengine/gaemiddleware"
|
| "github.com/luci/luci-go/common/clock"
|
| "github.com/luci/luci-go/server/auth"
|
| - "github.com/luci/luci-go/server/middleware"
|
| + "github.com/luci/luci-go/server/router"
|
| "github.com/luci/luci-go/server/templates"
|
| "golang.org/x/net/context"
|
| )
|
|
|
| type themeContextKey string
|
|
|
| // NamedBundle is a tuple of a name (That matches it's corresponding theme)
|
| // and a template bundle.
|
| type NamedBundle struct {
|
| Name string
|
| @@ -112,81 +112,82 @@ func GetTemplateBundles() []NamedBundle {
|
| return result
|
| }
|
|
|
| // UseNamedBundle is like templates.Use, but with the choice of one of many bundles (themes)
|
| func UseNamedBundle(c context.Context, nb NamedBundle) (context.Context, error) {
|
| err := nb.Bundle.EnsureLoaded(c)
|
| return context.WithValue(c, themeContextKey(nb.Name), nb.Bundle), err
|
| }
|
|
|
| // withNamedBundle is like templates.WithTemplates, but with the choice of one of many bundles (themes)
|
| -func withNamedBundle(h middleware.Handler, nb NamedBundle) middleware.Handler {
|
| - return func(c context.Context, rw http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
| - c, err := UseNamedBundle(c, nb) // calls EnsureLoaded and initializes b.err inside
|
| +func withNamedBundle(nb NamedBundle) router.Middleware {
|
| + return func(c *router.Context, next router.Handler) {
|
| + var err error
|
| + c.Context, err = UseNamedBundle(c.Context, nb) // calls EnsureLoaded and initializes b.err inside
|
| if err != nil {
|
| - http.Error(rw, fmt.Sprintf("Can't load HTML templates.\n%s", err), http.StatusInternalServerError)
|
| + http.Error(c.Writer, fmt.Sprintf("Can't load HTML templates.\n%s", err), http.StatusInternalServerError)
|
| return
|
| }
|
| - h(c, rw, r, p)
|
| + next(c)
|
| }
|
| }
|
|
|
| // themedMustRender renders theme and panics if it can't be rendered. This should never fail in
|
| // production.
|
| func themedMustRender(c context.Context, out io.Writer, theme, name string, args templates.Args) {
|
| if b, _ := c.Value(themeContextKey(theme)).(*templates.Bundle); b != nil {
|
| blob, err := b.Render(c, name, args)
|
| if err != nil {
|
| panic(fmt.Errorf("Could not render template %s from theme %s:\n%s", name, theme, err))
|
| }
|
| _, err = out.Write(blob)
|
| if err != nil {
|
| panic(fmt.Errorf("Could not write out template %s from theme %s:\n%s", name, theme, err))
|
| }
|
| return
|
| }
|
| panic(fmt.Errorf("Error: Could not load template %s from theme %s", name, theme))
|
| }
|
|
|
| -// Base adds the basic luci appengine middlewares.
|
| -func Base(h middleware.Handler) httprouter.Handle {
|
| +// Base returns the basic luci appengine middlewares.
|
| +func Base() router.MiddlewareChain {
|
| methods := auth.Authenticator{
|
| &server.OAuth2Method{Scopes: []string{server.EmailScope}},
|
| server.CookieAuth,
|
| &server.InboundAppIDAuthMethod{},
|
| }
|
| + m := append(gaemiddleware.BaseProd(), auth.Use(methods))
|
| for _, nb := range GetTemplateBundles() {
|
| - h = withNamedBundle(h, nb)
|
| + m = append(m, withNamedBundle(nb))
|
| }
|
| - return gaemiddleware.BaseProd(auth.Use(h, methods))
|
| + return m
|
| }
|
|
|
| -// Wrap wraps Milo "Render" functions and emits a middleware.Handler function. Of note
|
| -// is that Render functions' interface into rendering is purely through a single
|
| +// Wrap adapts a ThemedHandler into a router.Handler. Of note, the
|
| +// Render functions' interface into rendering is purely through a single
|
| // templates.Args value which gets rendered here, while the http.ResponseWriter
|
| // is stripped out.
|
| -func Wrap(h ThemedHandler) func(http.ResponseWriter, *http.Request, httprouter.Params) {
|
| - hx := func(c context.Context, w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
| +func Wrap(h ThemedHandler) router.Handler {
|
| + return func(c *router.Context) {
|
| // Figure out if we need to do the things.
|
| - theme := GetTheme(c, r)
|
| + theme := GetTheme(c.Context, c.Request)
|
| template := h.GetTemplateName(theme)
|
|
|
| // Do the things.
|
| - args, err := h.Render(c, r, p)
|
| + args, err := h.Render(c.Context, c.Request, c.Params)
|
|
|
| // Throw errors.
|
| // TODO(hinoka): Add themes and templates for errors so they look better.
|
| if err != nil {
|
| if merr, ok := err.(*miloerror.Error); ok {
|
| - http.Error(w, merr.Message, merr.Code)
|
| + http.Error(c.Writer, merr.Message, merr.Code)
|
| } else {
|
| - http.Error(w, err.Error(), http.StatusInternalServerError)
|
| + http.Error(c.Writer, err.Error(), http.StatusInternalServerError)
|
| }
|
| return
|
| }
|
|
|
| // Render the stuff.
|
| name := fmt.Sprintf("pages/%s", template)
|
| - themedMustRender(c, w, theme.Name, name, *args)
|
| + themedMustRender(c.Context, c.Writer, theme.Name, name, *args)
|
| }
|
| - return Base(hx)
|
| }
|
|
|