newBearerTokenFromHTTPResponseBody parses a http.Response to obtain a bearerToken. The caller is still responsible for ensuring res.Body is closed.
(res *http.Response)
| 858 | // newBearerTokenFromHTTPResponseBody parses a http.Response to obtain a bearerToken. |
| 859 | // The caller is still responsible for ensuring res.Body is closed. |
| 860 | func newBearerTokenFromHTTPResponseBody(res *http.Response) (*bearerToken, error) { |
| 861 | blob, err := iolimits.ReadAtMost(res.Body, iolimits.MaxAuthTokenBodySize) |
| 862 | if err != nil { |
| 863 | return nil, err |
| 864 | } |
| 865 | |
| 866 | var token struct { |
| 867 | Token string `json:"token"` |
| 868 | AccessToken string `json:"access_token"` |
| 869 | ExpiresIn int `json:"expires_in"` |
| 870 | IssuedAt time.Time `json:"issued_at"` |
| 871 | expirationTime time.Time |
| 872 | } |
| 873 | if err := json.Unmarshal(blob, &token); err != nil { |
| 874 | const bodySampleLength = 50 |
| 875 | bodySample := blob |
| 876 | if len(bodySample) > bodySampleLength { |
| 877 | bodySample = bodySample[:bodySampleLength] |
| 878 | } |
| 879 | return nil, fmt.Errorf("decoding bearer token (last URL %q, body start %q): %w", res.Request.URL.Redacted(), string(bodySample), err) |
| 880 | } |
| 881 | |
| 882 | bt := &bearerToken{ |
| 883 | token: token.Token, |
| 884 | } |
| 885 | if bt.token == "" { |
| 886 | bt.token = token.AccessToken |
| 887 | } |
| 888 | |
| 889 | if token.ExpiresIn < minimumTokenLifetimeSeconds { |
| 890 | token.ExpiresIn = minimumTokenLifetimeSeconds |
| 891 | logrus.Debugf("Increasing token expiration to: %d seconds", token.ExpiresIn) |
| 892 | } |
| 893 | if token.IssuedAt.IsZero() { |
| 894 | token.IssuedAt = time.Now().UTC() |
| 895 | } |
| 896 | bt.expirationTime = token.IssuedAt.Add(time.Duration(token.ExpiresIn) * time.Second) |
| 897 | return bt, nil |
| 898 | } |
| 899 | |
| 900 | // detectPropertiesHelper performs the work of detectProperties which executes |
| 901 | // it at most once. |
searching dependent graphs…