go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/appengine/gaemiddleware/standard/env.go (about) 1 // Copyright 2017 The LUCI Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package standard exposes a gaemiddleware Environment for Classic AppEngine. 16 package standard 17 18 import ( 19 "context" 20 "net/http" 21 "strings" 22 23 "google.golang.org/appengine" 24 25 "go.chromium.org/luci/common/tsmon/monitor" 26 "go.chromium.org/luci/common/tsmon/target" 27 "go.chromium.org/luci/config/appengine/gaeconfig" 28 "go.chromium.org/luci/config/validation" 29 "go.chromium.org/luci/server/auth" 30 "go.chromium.org/luci/server/auth/authdb" 31 "go.chromium.org/luci/server/middleware" 32 "go.chromium.org/luci/server/portal" 33 "go.chromium.org/luci/server/pprof" 34 "go.chromium.org/luci/server/router" 35 "go.chromium.org/luci/server/tsmon" 36 37 "go.chromium.org/luci/appengine/gaeauth/client" 38 gaeauth "go.chromium.org/luci/appengine/gaeauth/server" 39 "go.chromium.org/luci/appengine/gaeauth/server/gaesigner" 40 "go.chromium.org/luci/appengine/gaemiddleware" 41 gaetsmon "go.chromium.org/luci/appengine/tsmon" 42 43 "go.chromium.org/luci/gae/impl/prod" 44 "go.chromium.org/luci/gae/service/info" 45 ) 46 47 var ( 48 // globalAuthConfig is configuration of the server/auth library. 49 // 50 // It specifies concrete GAE-based implementations for various interfaces 51 // used by the library. 52 // 53 // It is indirectly stateful (since NewDBCache returns a stateful object that 54 // keeps AuthDB cache in local memory), and thus it's defined as a long living 55 // global variable. 56 // 57 // Used in prod contexts only. 58 globalAuthConfig = auth.Config{ 59 DBProvider: authdb.NewDBCache(gaeauth.GetAuthDB), 60 Signer: gaesigner.Signer{}, 61 AccessTokenProvider: client.GetAccessToken, 62 AnonymousTransport: func(ctx context.Context) http.RoundTripper { 63 return &contextAwareURLFetch{ctx} 64 }, 65 FrontendClientID: gaeauth.FetchFrontendClientID, 66 IsDevMode: appengine.IsDevAppServer(), 67 } 68 69 // globalTsMonState holds configuration and state related to time series 70 // monitoring. 71 globalTsMonState = &tsmon.State{ 72 CustomMonitor: tsmonDebugMonitor(), 73 Target: func(ctx context.Context) target.Task { 74 return target.Task{ 75 DataCenter: "appengine", 76 ServiceName: info.AppID(ctx), 77 JobName: info.ModuleName(ctx), 78 HostName: strings.SplitN(info.VersionID(ctx), ".", 2)[0], 79 } 80 }, 81 InstanceID: info.InstanceID, 82 TaskNumAllocator: gaetsmon.DatastoreTaskNumAllocator{}, 83 FlushInMiddleware: true, 84 } 85 ) 86 87 // tsmonDebugMonitor returns debug monitor when running on dev server. 88 func tsmonDebugMonitor() monitor.Monitor { 89 if appengine.IsDevAppServer() { 90 return monitor.NewDebugMonitor("") 91 } 92 return nil 93 } 94 95 // classicEnv is an AppEngine Classic GAE environment configuration. This is the 96 // default AppEngine environment for simple (all-classic) layouts. 97 var classicEnv = gaemiddleware.Environment{ 98 MemcacheAvailable: true, 99 WithInitialRequest: prod.Use, 100 WithConfig: gaeconfig.Use, 101 WithAuth: func(ctx context.Context) context.Context { 102 return auth.Initialize(ctx, &globalAuthConfig) 103 }, 104 105 ExtraMiddleware: func() router.MiddlewareChain { 106 mw := make([]router.Middleware, 0, 2) 107 if !appengine.IsDevAppServer() { 108 mw = append(mw, middleware.WithPanicCatcher) 109 } 110 mw = append(mw, globalTsMonState.Middleware) 111 return router.NewMiddlewareChain(mw...) 112 }(), 113 114 ExtraHandlers: func(r *router.Router, base router.MiddlewareChain) { 115 gaeauth.InstallHandlers(r, base) 116 gaetsmon.InstallHandlers(r, base) 117 portal.InstallHandlers(r, base, &gaeauth.UsersAPIAuthMethod{}) 118 gaeconfig.InstallValidationHandlers(r, base, &validation.Rules) 119 pprof.InstallHandlers(r, base) 120 }, 121 } 122 123 // With adds various production GAE LUCI services to the context. 124 // 125 // Basically, it installs GAE-specific backends and caches for various 126 // subsystems to make them work in GAE environment. 127 // 128 // One example is a backend for Logging: go.chromium.org/luci/common/logging. 129 // Logs emitted through a With() context go to GAE logs. 130 // 131 // 'Production' here means the services will use real GAE APIs (not mocks or 132 // stubs), so With should never be used from unit tests. 133 func With(ctx context.Context, req *http.Request) context.Context { 134 return classicEnv.With(ctx, req) 135 } 136 137 // Base returns a middleware chain to use for all GAE requests. 138 // 139 // This middleware chain installs prod GAE services into the request context 140 // (via With), and wraps the request with a panic catcher and monitoring 141 // hooks. 142 func Base() router.MiddlewareChain { return classicEnv.Base() } 143 144 // InstallHandlers installs handlers for framework routes using classic 145 // production services' default middleware. 146 // 147 // See InstallHandlersWithMiddleware for more information. 148 func InstallHandlers(r *router.Router) { classicEnv.InstallHandlers(r) } 149 150 // InstallHandlersWithMiddleware installs handlers for framework routes using 151 // classic production services. 152 // 153 // These routes are needed for various services provided in Base context to 154 // work: 155 // - Authentication related routes (gaeauth) 156 // - Settings pages (gaesettings) 157 // - Various housekeeping crons (tsmon, gaeconfig) 158 // - Warmup (warmup) 159 // 160 // They must be installed into a default module, but it is also safe to 161 // install them into a non-default module. This may be handy if you want to 162 // move cron handlers into a non-default module. 163 // 164 // 'base' is expected to be an Environment's Base() or its derivative. It must 165 // NOT do any interception of requests (e.g. checking and rejecting 166 // unauthenticated requests). 167 func InstallHandlersWithMiddleware(r *router.Router, base router.MiddlewareChain) { 168 classicEnv.InstallHandlersWithMiddleware(r, base) 169 }