github.com/timstclair/heapster@v0.20.0-alpha1/Godeps/_workspace/src/google.golang.org/appengine/internal/api_classic.go (about) 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 "net/http" 12 "time" 13 14 "appengine" 15 "appengine_internal" 16 basepb "appengine_internal/base" 17 18 "github.com/golang/protobuf/proto" 19 netcontext "golang.org/x/net/context" 20 ) 21 22 var contextKey = "holds an appengine.Context" 23 24 func fromContext(ctx netcontext.Context) appengine.Context { 25 c, _ := ctx.Value(&contextKey).(appengine.Context) 26 return c 27 } 28 29 // This is only for classic App Engine adapters. 30 func ClassicContextFromContext(ctx netcontext.Context) appengine.Context { 31 return fromContext(ctx) 32 } 33 34 func withContext(parent netcontext.Context, c appengine.Context) netcontext.Context { 35 ctx := netcontext.WithValue(parent, &contextKey, c) 36 37 s := &basepb.StringProto{} 38 c.Call("__go__", "GetNamespace", &basepb.VoidProto{}, s, nil) 39 if ns := s.GetValue(); ns != "" { 40 ctx = NamespacedContext(ctx, ns) 41 } 42 43 return ctx 44 } 45 46 func IncomingHeaders(ctx netcontext.Context) http.Header { 47 if c := fromContext(ctx); c != nil { 48 if req, ok := c.Request().(*http.Request); ok { 49 return req.Header 50 } 51 } 52 return nil 53 } 54 55 func WithContext(parent netcontext.Context, req *http.Request) netcontext.Context { 56 c := appengine.NewContext(req) 57 return withContext(parent, c) 58 } 59 60 func Call(ctx netcontext.Context, service, method string, in, out proto.Message) error { 61 if f, ctx, ok := callOverrideFromContext(ctx); ok { 62 return f(ctx, service, method, in, out) 63 } 64 65 // Handle already-done contexts quickly. 66 select { 67 case <-ctx.Done(): 68 return ctx.Err() 69 default: 70 } 71 72 c := fromContext(ctx) 73 if c == nil { 74 // Give a good error message rather than a panic lower down. 75 return errors.New("not an App Engine context") 76 } 77 78 // Apply transaction modifications if we're in a transaction. 79 if t := transactionFromContext(ctx); t != nil { 80 if t.finished { 81 return errors.New("transaction context has expired") 82 } 83 applyTransaction(in, &t.transaction) 84 } 85 86 var opts *appengine_internal.CallOptions 87 if d, ok := ctx.Deadline(); ok { 88 opts = &appengine_internal.CallOptions{ 89 Timeout: d.Sub(time.Now()), 90 } 91 } 92 93 err := c.Call(service, method, in, out, opts) 94 switch v := err.(type) { 95 case *appengine_internal.APIError: 96 return &APIError{ 97 Service: v.Service, 98 Detail: v.Detail, 99 Code: v.Code, 100 } 101 case *appengine_internal.CallError: 102 return &CallError{ 103 Detail: v.Detail, 104 Code: v.Code, 105 Timeout: v.Timeout, 106 } 107 } 108 return err 109 } 110 111 func handleHTTP(w http.ResponseWriter, r *http.Request) { 112 panic("handleHTTP called; this should be impossible") 113 } 114 115 func logf(c appengine.Context, level int64, format string, args ...interface{}) { 116 var fn func(format string, args ...interface{}) 117 switch level { 118 case 0: 119 fn = c.Debugf 120 case 1: 121 fn = c.Infof 122 case 2: 123 fn = c.Warningf 124 case 3: 125 fn = c.Errorf 126 case 4: 127 fn = c.Criticalf 128 default: 129 // This shouldn't happen. 130 fn = c.Criticalf 131 } 132 fn(format, args...) 133 }