OLD | NEW |
---|---|
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 prod | 5 package prod |
6 | 6 |
7 import ( | 7 import ( |
8 "fmt" | 8 "fmt" |
9 "net/http" | 9 "net/http" |
10 "net/http/cookiejar" | 10 "net/http/cookiejar" |
(...skipping 14 matching lines...) Expand all Loading... | |
25 "https://www.googleapis.com/auth/cloud.platform", | 25 "https://www.googleapis.com/auth/cloud.platform", |
26 } | 26 } |
27 | 27 |
28 type key int | 28 type key int |
29 | 29 |
30 var ( | 30 var ( |
31 prodStateKey = "contains the current *prodState" | 31 prodStateKey = "contains the current *prodState" |
32 probeCacheKey = "contains the current *infoProbeCache" | 32 probeCacheKey = "contains the current *infoProbeCache" |
33 ) | 33 ) |
34 | 34 |
35 // AEContext retrieves the raw "google.golang.org/appengine" compatible Context. | 35 // getAEContext retrieves the raw "google.golang.org/appengine" compatible |
36 // Context. | |
36 // | 37 // |
37 // It also transfers deadline of `c` to AE context, since deadline is used for | 38 // This is an independent Context chain from `c`. In an attempt to maintain user |
38 // RPCs. Doesn't transfer cancelation ability though (since it's ignored by GAE | 39 // expectations, the deadline of `c` is transferred to the returned Context, |
39 // anyway). | 40 // RPCs. Cancelation is not transferred. |
40 func AEContext(c context.Context) context.Context { | 41 func getAEContext(c context.Context) context.Context { |
41 ps := getProdState(c) | 42 ps := getProdState(c) |
42 return ps.context(c) | 43 return ps.context(c) |
43 } | 44 } |
44 | 45 |
45 func setupAECtx(c, aeCtx context.Context) context.Context { | 46 func setupAECtx(c, aeCtx context.Context) context.Context { |
46 c = withProdState(c, prodState{ | 47 c = withProdState(c, prodState{ |
47 ctx: aeCtx, | 48 ctx: aeCtx, |
48 noTxnCtx: aeCtx, | 49 noTxnCtx: aeCtx, |
49 }) | 50 }) |
50 return useModule(useMail(useUser(useURLFetch(useRDS(useMC(useTQ(useGI(us eLogging(c))))))))) | 51 return useModule(useMail(useUser(useURLFetch(useRDS(useMC(useTQ(useGI(us eLogging(c))))))))) |
51 } | 52 } |
52 | 53 |
53 // Use adds production implementations for all the gae services to the | 54 // Use adds production implementations for all the gae services to the |
54 // context. | 55 // context. The implementations are all backed by the real appengine SDK |
56 // functionality. | |
55 // | 57 // |
56 // The services added are: | 58 // The services added are: |
57 // - github.com/luci-go/common/logging | 59 // - github.com/luci-go/common/logging |
58 // - github.com/luci/gae/service/datastore | 60 // - github.com/luci/gae/service/datastore |
59 // - github.com/luci/gae/service/info | 61 // - github.com/luci/gae/service/info |
60 // - github.com/luci/gae/service/mail | 62 // - github.com/luci/gae/service/mail |
61 // - github.com/luci/gae/service/memcache | 63 // - github.com/luci/gae/service/memcache |
62 // - github.com/luci/gae/service/module | 64 // - github.com/luci/gae/service/module |
63 // - github.com/luci/gae/service/taskqueue | 65 // - github.com/luci/gae/service/taskqueue |
64 // - github.com/luci/gae/service/urlfetch | 66 // - github.com/luci/gae/service/urlfetch |
65 // - github.com/luci/gae/service/user | 67 // - github.com/luci/gae/service/user |
66 // | 68 // |
67 // These can be retrieved with the <service>.Get functions. | 69 // These can be retrieved with the <service>.Get functions. |
68 // | 70 // |
69 // The implementations are all backed by the real appengine SDK functionality, | 71 // It is important to note that this DOES NOT install the AppEngine SDK into the |
72 // supplied Context. In general, using raw AppEngine SDK alongside luci/gae is | |
73 // dangerous, leading to a number of pitfalls including inconsistent transaction | |
74 // management and memory corruption. Users who wish to access the raw AppEngine | |
75 // SDK must derive their own AppEngine Context; luci/gae will not help you. | |
iannucci
2016/10/28 18:40:16
I would note that using the raw AppEngine SDK to a
| |
70 func Use(c context.Context, r *http.Request) context.Context { | 76 func Use(c context.Context, r *http.Request) context.Context { |
71 return setupAECtx(c, appengine.NewContext(r)) | 77 return setupAECtx(c, appengine.NewContext(r)) |
72 } | 78 } |
73 | 79 |
74 // UseRemote is the same as Use, except that it lets you attach a context to | 80 // UseRemote is the same as Use, except that it lets you attach a context to |
75 // a remote host using the Remote API feature. See the docs for the | 81 // a remote host using the Remote API feature. See the docs for the |
76 // prerequisites. | 82 // prerequisites. |
77 // | 83 // |
78 // docs: https://cloud.google.com/appengine/docs/go/tools/remoteapi | 84 // docs: https://cloud.google.com/appengine/docs/go/tools/remoteapi |
79 // | 85 // |
80 // inOutCtx will be replaced with the new, derived context, if err is nil, | 86 // inOutCtx will be replaced with the new, derived context, if err is nil, |
81 // otherwise it's unchanged and continues to be safe-to-use. | 87 // otherwise it's unchanged and continues to be safe-to-use. |
82 // | 88 // |
83 // If client is nil, this will use create a new client, and will try to be | 89 // If client is nil, this will use create a new client, and will try to be |
84 // clever about it: | 90 // clever about it: |
85 // * If you're creating a remote context FROM AppEngine, this will use | 91 // * If you're creating a remote context FROM AppEngine, this will use |
86 // urlfetch.Transport. This can be used to allow app-to-app remote_api | 92 // urlfetch.Transport. This can be used to allow app-to-app remote_api |
87 // control. | 93 // control. |
88 // | 94 // |
89 // * If host starts with "localhost", this will create a regular http.Client | 95 // * If host starts with "localhost", this will create a regular http.Client |
90 // with a cookiejar, and call the _ah/login API to log in as an admin with | 96 // with a cookiejar, and call the _ah/login API to log in as an admin with |
91 // the user "admin@example.com". | 97 // the user "admin@example.com". |
92 // | 98 // |
93 // * Otherwise, it will create a Google OAuth2 client with the following scope s: | 99 // * Otherwise, it will create a Google OAuth2 client with the following scope s: |
94 // - "https://www.googleapis.com/auth/appengine.apis" | 100 // - "https://www.googleapis.com/auth/appengine.apis" |
95 // - "https://www.googleapis.com/auth/userinfo.email" | 101 // - "https://www.googleapis.com/auth/userinfo.email" |
96 // - "https://www.googleapis.com/auth/cloud.platform" | 102 // - "https://www.googleapis.com/auth/cloud.platform" |
103 // | |
104 // It is important to note that this DOES NOT install the AppEngine SDK into the | |
105 // supplied Context. See the warning in Use for more information. | |
97 func UseRemote(inOutCtx *context.Context, host string, client *http.Client) (err error) { | 106 func UseRemote(inOutCtx *context.Context, host string, client *http.Client) (err error) { |
98 if client == nil { | 107 if client == nil { |
99 » » aeCtx := AEContext(*inOutCtx) | 108 » » aeCtx := getAEContext(*inOutCtx) |
100 | 109 |
101 if strings.HasPrefix(host, "localhost") { | 110 if strings.HasPrefix(host, "localhost") { |
102 transp := http.DefaultTransport | 111 transp := http.DefaultTransport |
103 if aeCtx != nil { | 112 if aeCtx != nil { |
104 transp = urlfetch.Get(*inOutCtx) | 113 transp = urlfetch.Get(*inOutCtx) |
105 } | 114 } |
106 | 115 |
107 client = &http.Client{Transport: transp} | 116 client = &http.Client{Transport: transp} |
108 client.Jar, err = cookiejar.New(nil) | 117 client.Jar, err = cookiejar.New(nil) |
109 if err != nil { | 118 if err != nil { |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
177 aeCtx := ps.ctx | 186 aeCtx := ps.ctx |
178 if aeCtx == nil { | 187 if aeCtx == nil { |
179 return nil | 188 return nil |
180 } | 189 } |
181 | 190 |
182 if deadline, ok := c.Deadline(); ok { | 191 if deadline, ok := c.Deadline(); ok { |
183 aeCtx, _ = context.WithDeadline(aeCtx, deadline) | 192 aeCtx, _ = context.WithDeadline(aeCtx, deadline) |
184 } | 193 } |
185 return aeCtx | 194 return aeCtx |
186 } | 195 } |
OLD | NEW |