mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-11-02 16:52:25 -06:00 
			
		
		
		
	* start fixing up tests * fix up tests + automate with drone * fiddle with linting * messing about with drone.yml * some more fiddling * hmmm * add cache * add vendor directory * verbose * ci updates * update some little things * update sig
		
			
				
	
	
		
			169 lines
		
	
	
	
		
			3.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			169 lines
		
	
	
	
		
			3.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Copyright 2015 Google Inc. All rights reserved.
 | 
						|
// Use of this source code is governed by the Apache 2.0
 | 
						|
// license that can be found in the LICENSE file.
 | 
						|
 | 
						|
// +build appengine
 | 
						|
 | 
						|
package internal
 | 
						|
 | 
						|
import (
 | 
						|
	"errors"
 | 
						|
	"fmt"
 | 
						|
	"net/http"
 | 
						|
	"time"
 | 
						|
 | 
						|
	"appengine"
 | 
						|
	"appengine_internal"
 | 
						|
	basepb "appengine_internal/base"
 | 
						|
 | 
						|
	"github.com/golang/protobuf/proto"
 | 
						|
	netcontext "golang.org/x/net/context"
 | 
						|
)
 | 
						|
 | 
						|
var contextKey = "holds an appengine.Context"
 | 
						|
 | 
						|
// fromContext returns the App Engine context or nil if ctx is not
 | 
						|
// derived from an App Engine context.
 | 
						|
func fromContext(ctx netcontext.Context) appengine.Context {
 | 
						|
	c, _ := ctx.Value(&contextKey).(appengine.Context)
 | 
						|
	return c
 | 
						|
}
 | 
						|
 | 
						|
// This is only for classic App Engine adapters.
 | 
						|
func ClassicContextFromContext(ctx netcontext.Context) (appengine.Context, error) {
 | 
						|
	c := fromContext(ctx)
 | 
						|
	if c == nil {
 | 
						|
		return nil, errNotAppEngineContext
 | 
						|
	}
 | 
						|
	return c, nil
 | 
						|
}
 | 
						|
 | 
						|
func withContext(parent netcontext.Context, c appengine.Context) netcontext.Context {
 | 
						|
	ctx := netcontext.WithValue(parent, &contextKey, c)
 | 
						|
 | 
						|
	s := &basepb.StringProto{}
 | 
						|
	c.Call("__go__", "GetNamespace", &basepb.VoidProto{}, s, nil)
 | 
						|
	if ns := s.GetValue(); ns != "" {
 | 
						|
		ctx = NamespacedContext(ctx, ns)
 | 
						|
	}
 | 
						|
 | 
						|
	return ctx
 | 
						|
}
 | 
						|
 | 
						|
func IncomingHeaders(ctx netcontext.Context) http.Header {
 | 
						|
	if c := fromContext(ctx); c != nil {
 | 
						|
		if req, ok := c.Request().(*http.Request); ok {
 | 
						|
			return req.Header
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func ReqContext(req *http.Request) netcontext.Context {
 | 
						|
	return WithContext(netcontext.Background(), req)
 | 
						|
}
 | 
						|
 | 
						|
func WithContext(parent netcontext.Context, req *http.Request) netcontext.Context {
 | 
						|
	c := appengine.NewContext(req)
 | 
						|
	return withContext(parent, c)
 | 
						|
}
 | 
						|
 | 
						|
type testingContext struct {
 | 
						|
	appengine.Context
 | 
						|
 | 
						|
	req *http.Request
 | 
						|
}
 | 
						|
 | 
						|
func (t *testingContext) FullyQualifiedAppID() string { return "dev~testcontext" }
 | 
						|
func (t *testingContext) Call(service, method string, _, _ appengine_internal.ProtoMessage, _ *appengine_internal.CallOptions) error {
 | 
						|
	if service == "__go__" && method == "GetNamespace" {
 | 
						|
		return nil
 | 
						|
	}
 | 
						|
	return fmt.Errorf("testingContext: unsupported Call")
 | 
						|
}
 | 
						|
func (t *testingContext) Request() interface{} { return t.req }
 | 
						|
 | 
						|
func ContextForTesting(req *http.Request) netcontext.Context {
 | 
						|
	return withContext(netcontext.Background(), &testingContext{req: req})
 | 
						|
}
 | 
						|
 | 
						|
func Call(ctx netcontext.Context, service, method string, in, out proto.Message) error {
 | 
						|
	if ns := NamespaceFromContext(ctx); ns != "" {
 | 
						|
		if fn, ok := NamespaceMods[service]; ok {
 | 
						|
			fn(in, ns)
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if f, ctx, ok := callOverrideFromContext(ctx); ok {
 | 
						|
		return f(ctx, service, method, in, out)
 | 
						|
	}
 | 
						|
 | 
						|
	// Handle already-done contexts quickly.
 | 
						|
	select {
 | 
						|
	case <-ctx.Done():
 | 
						|
		return ctx.Err()
 | 
						|
	default:
 | 
						|
	}
 | 
						|
 | 
						|
	c := fromContext(ctx)
 | 
						|
	if c == nil {
 | 
						|
		// Give a good error message rather than a panic lower down.
 | 
						|
		return errNotAppEngineContext
 | 
						|
	}
 | 
						|
 | 
						|
	// Apply transaction modifications if we're in a transaction.
 | 
						|
	if t := transactionFromContext(ctx); t != nil {
 | 
						|
		if t.finished {
 | 
						|
			return errors.New("transaction context has expired")
 | 
						|
		}
 | 
						|
		applyTransaction(in, &t.transaction)
 | 
						|
	}
 | 
						|
 | 
						|
	var opts *appengine_internal.CallOptions
 | 
						|
	if d, ok := ctx.Deadline(); ok {
 | 
						|
		opts = &appengine_internal.CallOptions{
 | 
						|
			Timeout: d.Sub(time.Now()),
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	err := c.Call(service, method, in, out, opts)
 | 
						|
	switch v := err.(type) {
 | 
						|
	case *appengine_internal.APIError:
 | 
						|
		return &APIError{
 | 
						|
			Service: v.Service,
 | 
						|
			Detail:  v.Detail,
 | 
						|
			Code:    v.Code,
 | 
						|
		}
 | 
						|
	case *appengine_internal.CallError:
 | 
						|
		return &CallError{
 | 
						|
			Detail:  v.Detail,
 | 
						|
			Code:    v.Code,
 | 
						|
			Timeout: v.Timeout,
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return err
 | 
						|
}
 | 
						|
 | 
						|
func handleHTTP(w http.ResponseWriter, r *http.Request) {
 | 
						|
	panic("handleHTTP called; this should be impossible")
 | 
						|
}
 | 
						|
 | 
						|
func logf(c appengine.Context, level int64, format string, args ...interface{}) {
 | 
						|
	var fn func(format string, args ...interface{})
 | 
						|
	switch level {
 | 
						|
	case 0:
 | 
						|
		fn = c.Debugf
 | 
						|
	case 1:
 | 
						|
		fn = c.Infof
 | 
						|
	case 2:
 | 
						|
		fn = c.Warningf
 | 
						|
	case 3:
 | 
						|
		fn = c.Errorf
 | 
						|
	case 4:
 | 
						|
		fn = c.Criticalf
 | 
						|
	default:
 | 
						|
		// This shouldn't happen.
 | 
						|
		fn = c.Criticalf
 | 
						|
	}
 | 
						|
	fn(format, args...)
 | 
						|
}
 |