gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

api_classic.go (4041B)


      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 }