diff options
Diffstat (limited to 'vendor/google.golang.org/appengine/internal/api_classic.go')
-rw-r--r-- | vendor/google.golang.org/appengine/internal/api_classic.go | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/vendor/google.golang.org/appengine/internal/api_classic.go b/vendor/google.golang.org/appengine/internal/api_classic.go new file mode 100644 index 0000000..f0f40b2 --- /dev/null +++ b/vendor/google.golang.org/appengine/internal/api_classic.go | |||
@@ -0,0 +1,169 @@ | |||
1 | // Copyright 2015 Google Inc. All rights reserved. | ||
2 | // Use of this source code is governed by the Apache 2.0 | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | // +build appengine | ||
6 | |||
7 | package internal | ||
8 | |||
9 | import ( | ||
10 | "errors" | ||
11 | "fmt" | ||
12 | "net/http" | ||
13 | "time" | ||
14 | |||
15 | "appengine" | ||
16 | "appengine_internal" | ||
17 | basepb "appengine_internal/base" | ||
18 | |||
19 | "github.com/golang/protobuf/proto" | ||
20 | netcontext "golang.org/x/net/context" | ||
21 | ) | ||
22 | |||
23 | var contextKey = "holds an appengine.Context" | ||
24 | |||
25 | // fromContext returns the App Engine context or nil if ctx is not | ||
26 | // derived from an App Engine context. | ||
27 | func fromContext(ctx netcontext.Context) appengine.Context { | ||
28 | c, _ := ctx.Value(&contextKey).(appengine.Context) | ||
29 | return c | ||
30 | } | ||
31 | |||
32 | // This is only for classic App Engine adapters. | ||
33 | func ClassicContextFromContext(ctx netcontext.Context) (appengine.Context, error) { | ||
34 | c := fromContext(ctx) | ||
35 | if c == nil { | ||
36 | return nil, errNotAppEngineContext | ||
37 | } | ||
38 | return c, nil | ||
39 | } | ||
40 | |||
41 | func withContext(parent netcontext.Context, c appengine.Context) netcontext.Context { | ||
42 | ctx := netcontext.WithValue(parent, &contextKey, c) | ||
43 | |||
44 | s := &basepb.StringProto{} | ||
45 | c.Call("__go__", "GetNamespace", &basepb.VoidProto{}, s, nil) | ||
46 | if ns := s.GetValue(); ns != "" { | ||
47 | ctx = NamespacedContext(ctx, ns) | ||
48 | } | ||
49 | |||
50 | return ctx | ||
51 | } | ||
52 | |||
53 | func IncomingHeaders(ctx netcontext.Context) http.Header { | ||
54 | if c := fromContext(ctx); c != nil { | ||
55 | if req, ok := c.Request().(*http.Request); ok { | ||
56 | return req.Header | ||
57 | } | ||
58 | } | ||
59 | return nil | ||
60 | } | ||
61 | |||
62 | func ReqContext(req *http.Request) netcontext.Context { | ||
63 | return WithContext(netcontext.Background(), req) | ||
64 | } | ||
65 | |||
66 | func WithContext(parent netcontext.Context, req *http.Request) netcontext.Context { | ||
67 | c := appengine.NewContext(req) | ||
68 | return withContext(parent, c) | ||
69 | } | ||
70 | |||
71 | type testingContext struct { | ||
72 | appengine.Context | ||
73 | |||
74 | req *http.Request | ||
75 | } | ||
76 | |||
77 | func (t *testingContext) FullyQualifiedAppID() string { return "dev~testcontext" } | ||
78 | func (t *testingContext) Call(service, method string, _, _ appengine_internal.ProtoMessage, _ *appengine_internal.CallOptions) error { | ||
79 | if service == "__go__" && method == "GetNamespace" { | ||
80 | return nil | ||
81 | } | ||
82 | return fmt.Errorf("testingContext: unsupported Call") | ||
83 | } | ||
84 | func (t *testingContext) Request() interface{} { return t.req } | ||
85 | |||
86 | func ContextForTesting(req *http.Request) netcontext.Context { | ||
87 | return withContext(netcontext.Background(), &testingContext{req: req}) | ||
88 | } | ||
89 | |||
90 | func Call(ctx netcontext.Context, service, method string, in, out proto.Message) error { | ||
91 | if ns := NamespaceFromContext(ctx); ns != "" { | ||
92 | if fn, ok := NamespaceMods[service]; ok { | ||
93 | fn(in, ns) | ||
94 | } | ||
95 | } | ||
96 | |||
97 | if f, ctx, ok := callOverrideFromContext(ctx); ok { | ||
98 | return f(ctx, service, method, in, out) | ||
99 | } | ||
100 | |||
101 | // Handle already-done contexts quickly. | ||
102 | select { | ||
103 | case <-ctx.Done(): | ||
104 | return ctx.Err() | ||
105 | default: | ||
106 | } | ||
107 | |||
108 | c := fromContext(ctx) | ||
109 | if c == nil { | ||
110 | // Give a good error message rather than a panic lower down. | ||
111 | return errNotAppEngineContext | ||
112 | } | ||
113 | |||
114 | // Apply transaction modifications if we're in a transaction. | ||
115 | if t := transactionFromContext(ctx); t != nil { | ||
116 | if t.finished { | ||
117 | return errors.New("transaction context has expired") | ||
118 | } | ||
119 | applyTransaction(in, &t.transaction) | ||
120 | } | ||
121 | |||
122 | var opts *appengine_internal.CallOptions | ||
123 | if d, ok := ctx.Deadline(); ok { | ||
124 | opts = &appengine_internal.CallOptions{ | ||
125 | Timeout: d.Sub(time.Now()), | ||
126 | } | ||
127 | } | ||
128 | |||
129 | err := c.Call(service, method, in, out, opts) | ||
130 | switch v := err.(type) { | ||
131 | case *appengine_internal.APIError: | ||
132 | return &APIError{ | ||
133 | Service: v.Service, | ||
134 | Detail: v.Detail, | ||
135 | Code: v.Code, | ||
136 | } | ||
137 | case *appengine_internal.CallError: | ||
138 | return &CallError{ | ||
139 | Detail: v.Detail, | ||
140 | Code: v.Code, | ||
141 | Timeout: v.Timeout, | ||
142 | } | ||
143 | } | ||
144 | return err | ||
145 | } | ||
146 | |||
147 | func handleHTTP(w http.ResponseWriter, r *http.Request) { | ||
148 | panic("handleHTTP called; this should be impossible") | ||
149 | } | ||
150 | |||
151 | func logf(c appengine.Context, level int64, format string, args ...interface{}) { | ||
152 | var fn func(format string, args ...interface{}) | ||
153 | switch level { | ||
154 | case 0: | ||
155 | fn = c.Debugf | ||
156 | case 1: | ||
157 | fn = c.Infof | ||
158 | case 2: | ||
159 | fn = c.Warningf | ||
160 | case 3: | ||
161 | fn = c.Errorf | ||
162 | case 4: | ||
163 | fn = c.Criticalf | ||
164 | default: | ||
165 | // This shouldn't happen. | ||
166 | fn = c.Criticalf | ||
167 | } | ||
168 | fn(format, args...) | ||
169 | } | ||