Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(411)

Side by Side Diff: appengine/cmd/milo/settings/themes.go

Issue 2043423004: Make HTTP middleware easier to use (Closed) Base URL: https://github.com/luci/luci-go@master
Patch Set: Convert remaining source files Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « appengine/cmd/milo/settings/settings.go ('k') | appengine/cmd/tokenserver/frontend/main.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The LUCI Authors. All rights reserved. 1 // Copyright 2015 The LUCI Authors. All rights reserved.
2 // Use of this source code is governed under the Apache License, Version 2.0 2 // Use of this source code is governed under the Apache License, Version 2.0
3 // that can be found in the LICENSE file. 3 // that can be found in the LICENSE file.
4 4
5 package settings 5 package settings
6 6
7 import ( 7 import (
8 "fmt" 8 "fmt"
9 "io" 9 "io"
10 "net/http" 10 "net/http"
11 "path" 11 "path"
12 "sort" 12 "sort"
13 "strings" 13 "strings"
14 14
15 "google.golang.org/appengine" 15 "google.golang.org/appengine"
16 16
17 "github.com/julienschmidt/httprouter" 17 "github.com/julienschmidt/httprouter"
18 "github.com/luci/gae/service/info" 18 "github.com/luci/gae/service/info"
19 "github.com/luci/luci-go/appengine/cmd/milo/miloerror" 19 "github.com/luci/luci-go/appengine/cmd/milo/miloerror"
20 "github.com/luci/luci-go/appengine/gaeauth/server" 20 "github.com/luci/luci-go/appengine/gaeauth/server"
21 "github.com/luci/luci-go/appengine/gaemiddleware" 21 "github.com/luci/luci-go/appengine/gaemiddleware"
22 "github.com/luci/luci-go/common/clock" 22 "github.com/luci/luci-go/common/clock"
23 "github.com/luci/luci-go/server/auth" 23 "github.com/luci/luci-go/server/auth"
24 » "github.com/luci/luci-go/server/middleware" 24 » "github.com/luci/luci-go/server/router"
25 "github.com/luci/luci-go/server/templates" 25 "github.com/luci/luci-go/server/templates"
26 "golang.org/x/net/context" 26 "golang.org/x/net/context"
27 ) 27 )
28 28
29 type themeContextKey string 29 type themeContextKey string
30 30
31 // NamedBundle is a tuple of a name (That matches it's corresponding theme) 31 // NamedBundle is a tuple of a name (That matches it's corresponding theme)
32 // and a template bundle. 32 // and a template bundle.
33 type NamedBundle struct { 33 type NamedBundle struct {
34 Name string 34 Name string
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
112 return result 112 return result
113 } 113 }
114 114
115 // UseNamedBundle is like templates.Use, but with the choice of one of many bund les (themes) 115 // UseNamedBundle is like templates.Use, but with the choice of one of many bund les (themes)
116 func UseNamedBundle(c context.Context, nb NamedBundle) (context.Context, error) { 116 func UseNamedBundle(c context.Context, nb NamedBundle) (context.Context, error) {
117 err := nb.Bundle.EnsureLoaded(c) 117 err := nb.Bundle.EnsureLoaded(c)
118 return context.WithValue(c, themeContextKey(nb.Name), nb.Bundle), err 118 return context.WithValue(c, themeContextKey(nb.Name), nb.Bundle), err
119 } 119 }
120 120
121 // withNamedBundle is like templates.WithTemplates, but with the choice of one o f many bundles (themes) 121 // withNamedBundle is like templates.WithTemplates, but with the choice of one o f many bundles (themes)
122 func withNamedBundle(h middleware.Handler, nb NamedBundle) middleware.Handler { 122 func withNamedBundle(nb NamedBundle) router.Middleware {
123 » return func(c context.Context, rw http.ResponseWriter, r *http.Request, p httprouter.Params) { 123 » return func(c *router.Context, next router.Handler) {
124 » » c, err := UseNamedBundle(c, nb) // calls EnsureLoaded and initia lizes b.err inside 124 » » var err error
125 » » c.Context, err = UseNamedBundle(c.Context, nb) // calls EnsureLo aded and initializes b.err inside
125 if err != nil { 126 if err != nil {
126 » » » http.Error(rw, fmt.Sprintf("Can't load HTML templates.\n %s", err), http.StatusInternalServerError) 127 » » » http.Error(c.Writer, fmt.Sprintf("Can't load HTML templa tes.\n%s", err), http.StatusInternalServerError)
127 return 128 return
128 } 129 }
129 » » h(c, rw, r, p) 130 » » next(c)
130 } 131 }
131 } 132 }
132 133
133 // themedMustRender renders theme and panics if it can't be rendered. This shou ld never fail in 134 // themedMustRender renders theme and panics if it can't be rendered. This shou ld never fail in
134 // production. 135 // production.
135 func themedMustRender(c context.Context, out io.Writer, theme, name string, args templates.Args) { 136 func themedMustRender(c context.Context, out io.Writer, theme, name string, args templates.Args) {
136 if b, _ := c.Value(themeContextKey(theme)).(*templates.Bundle); b != nil { 137 if b, _ := c.Value(themeContextKey(theme)).(*templates.Bundle); b != nil {
137 blob, err := b.Render(c, name, args) 138 blob, err := b.Render(c, name, args)
138 if err != nil { 139 if err != nil {
139 panic(fmt.Errorf("Could not render template %s from them e %s:\n%s", name, theme, err)) 140 panic(fmt.Errorf("Could not render template %s from them e %s:\n%s", name, theme, err))
140 } 141 }
141 _, err = out.Write(blob) 142 _, err = out.Write(blob)
142 if err != nil { 143 if err != nil {
143 panic(fmt.Errorf("Could not write out template %s from t heme %s:\n%s", name, theme, err)) 144 panic(fmt.Errorf("Could not write out template %s from t heme %s:\n%s", name, theme, err))
144 } 145 }
145 return 146 return
146 } 147 }
147 panic(fmt.Errorf("Error: Could not load template %s from theme %s", name , theme)) 148 panic(fmt.Errorf("Error: Could not load template %s from theme %s", name , theme))
148 } 149 }
149 150
150 // Base adds the basic luci appengine middlewares. 151 // Base returns the basic luci appengine middlewares.
151 func Base(h middleware.Handler) httprouter.Handle { 152 func Base() router.MiddlewareChain {
152 methods := auth.Authenticator{ 153 methods := auth.Authenticator{
153 &server.OAuth2Method{Scopes: []string{server.EmailScope}}, 154 &server.OAuth2Method{Scopes: []string{server.EmailScope}},
154 server.CookieAuth, 155 server.CookieAuth,
155 &server.InboundAppIDAuthMethod{}, 156 &server.InboundAppIDAuthMethod{},
156 } 157 }
158 m := append(gaemiddleware.BaseProd(), auth.Use(methods))
157 for _, nb := range GetTemplateBundles() { 159 for _, nb := range GetTemplateBundles() {
158 » » h = withNamedBundle(h, nb) 160 » » m = append(m, withNamedBundle(nb))
nishanths 2016/06/20 15:14:29 The bundles are now in reverse order in the middle
159 } 161 }
160 » return gaemiddleware.BaseProd(auth.Use(h, methods)) 162 » return m
161 } 163 }
162 164
163 // Wrap wraps Milo "Render" functions and emits a middleware.Handler function. Of note 165 // Wrap adapts a ThemedHandler into a router.Handler. Of note, the
164 // is that Render functions' interface into rendering is purely through a single 166 // Render functions' interface into rendering is purely through a single
165 // templates.Args value which gets rendered here, while the http.ResponseWriter 167 // templates.Args value which gets rendered here, while the http.ResponseWriter
166 // is stripped out. 168 // is stripped out.
167 func Wrap(h ThemedHandler) func(http.ResponseWriter, *http.Request, httprouter.P arams) { 169 func Wrap(h ThemedHandler) router.Handler {
168 » hx := func(c context.Context, w http.ResponseWriter, r *http.Request, p httprouter.Params) { 170 » return func(c *router.Context) {
169 // Figure out if we need to do the things. 171 // Figure out if we need to do the things.
170 » » theme := GetTheme(c, r) 172 » » theme := GetTheme(c.Context, c.Request)
171 template := h.GetTemplateName(theme) 173 template := h.GetTemplateName(theme)
172 174
173 // Do the things. 175 // Do the things.
174 » » args, err := h.Render(c, r, p) 176 » » args, err := h.Render(c.Context, c.Request, c.Params)
175 177
176 // Throw errors. 178 // Throw errors.
177 // TODO(hinoka): Add themes and templates for errors so they loo k better. 179 // TODO(hinoka): Add themes and templates for errors so they loo k better.
178 if err != nil { 180 if err != nil {
179 if merr, ok := err.(*miloerror.Error); ok { 181 if merr, ok := err.(*miloerror.Error); ok {
180 » » » » http.Error(w, merr.Message, merr.Code) 182 » » » » http.Error(c.Writer, merr.Message, merr.Code)
181 } else { 183 } else {
182 » » » » http.Error(w, err.Error(), http.StatusInternalSe rverError) 184 » » » » http.Error(c.Writer, err.Error(), http.StatusInt ernalServerError)
183 } 185 }
184 return 186 return
185 } 187 }
186 188
187 // Render the stuff. 189 // Render the stuff.
188 name := fmt.Sprintf("pages/%s", template) 190 name := fmt.Sprintf("pages/%s", template)
189 » » themedMustRender(c, w, theme.Name, name, *args) 191 » » themedMustRender(c.Context, c.Writer, theme.Name, name, *args)
190 } 192 }
191 return Base(hx)
192 } 193 }
OLDNEW
« no previous file with comments | « appengine/cmd/milo/settings/settings.go ('k') | appengine/cmd/tokenserver/frontend/main.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698