appengine_gen1.go 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. // Copyright 2018 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. //go:build appengine
  5. // +build appengine
  6. // This file applies to App Engine first generation runtimes (<= Go 1.9).
  7. package google
  8. import (
  9. "context"
  10. "sort"
  11. "strings"
  12. "sync"
  13. "golang.org/x/oauth2"
  14. "google.golang.org/appengine"
  15. )
  16. func init() {
  17. appengineTokenFunc = appengine.AccessToken
  18. appengineAppIDFunc = appengine.AppID
  19. }
  20. // See comment on AppEngineTokenSource in appengine.go.
  21. func appEngineTokenSource(ctx context.Context, scope ...string) oauth2.TokenSource {
  22. scopes := append([]string{}, scope...)
  23. sort.Strings(scopes)
  24. return &gaeTokenSource{
  25. ctx: ctx,
  26. scopes: scopes,
  27. key: strings.Join(scopes, " "),
  28. }
  29. }
  30. // aeTokens helps the fetched tokens to be reused until their expiration.
  31. var (
  32. aeTokensMu sync.Mutex
  33. aeTokens = make(map[string]*tokenLock) // key is space-separated scopes
  34. )
  35. type tokenLock struct {
  36. mu sync.Mutex // guards t; held while fetching or updating t
  37. t *oauth2.Token
  38. }
  39. type gaeTokenSource struct {
  40. ctx context.Context
  41. scopes []string
  42. key string // to aeTokens map; space-separated scopes
  43. }
  44. func (ts *gaeTokenSource) Token() (*oauth2.Token, error) {
  45. aeTokensMu.Lock()
  46. tok, ok := aeTokens[ts.key]
  47. if !ok {
  48. tok = &tokenLock{}
  49. aeTokens[ts.key] = tok
  50. }
  51. aeTokensMu.Unlock()
  52. tok.mu.Lock()
  53. defer tok.mu.Unlock()
  54. if tok.t.Valid() {
  55. return tok.t, nil
  56. }
  57. access, exp, err := appengineTokenFunc(ts.ctx, ts.scopes...)
  58. if err != nil {
  59. return nil, err
  60. }
  61. tok.t = &oauth2.Token{
  62. AccessToken: access,
  63. Expiry: exp,
  64. }
  65. return tok.t, nil
  66. }