-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Fix credentials usage in BatchHTTPRequest #376
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Please don't merge until I verify this will fix #375 and have a chance to write tests. |
@jonparrott Looks like there is a circular import issue
Now going beyond that, the _serialize_request method should also be updated with the _auth.get_credentials_from_http method, which leads to issue #350. So I think we should change the _serialize_request from: if request.http is not None and hasattr(request.http.request,
'credentials'):
request.http.request.credentials.apply(headers) to if request.http is not None:
creds = _auth.get_credentials_from_http(request.http)
if creds is not None:
if _auth.has_access_token(creds):
creds.apply(headers) |
'credentials'): | ||
request.http.request.credentials.apply(headers) | ||
if request.http is not None: | ||
credentials = _auth.get_credentials_from_http(request.http) |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
@jonparrott Just tried this, everything's good ! |
@jonparrott Actually I'm seeing something that might be a bit off from a couple of tests I just performed. In the execute() method, in the case where we have no initial token, we manually refresh the credentials providing the http instance (either the one given to the execute method or the one from the first request in the batch): # Special case for OAuth2Credentials-style objects which have not yet been
# refreshed with an initial access_token.
creds = _auth.get_credentials_from_http(http)
if creds is not None:
if not _auth.has_access_token(creds):
LOGGER.info('Attempting refresh to obtain initial access_token')
_auth.refresh_credentials(creds, http)
self._execute(http, self._order, self._requests) Now in _auth.refresh_credentials method, in the case of google-auth credentials we do this: request = google_auth_httplib2.Request(http)
return credentials.refresh(request) We're building a Request object using the provided http instance, which in this case will be an AuthorizedHttp object. That means it will use the AuthorizedHttp.request method to perform the request that will get an access token. However, this request method also performs a token refresh if needed. So what I observed is that when we have no initial token for google-auth credentials, the token gets refreshed twice: once because we manually called credentials.refresh and once because the request method used to refresh this token also performs a token refresh. So my suggestion would be to use a new httplib2.Http() object for the request. request = google_auth_httplib2.Request(httplib2.Http())
return credentials.refresh(request) This way the credentials are refreshed only once. What do you think ? |
@sbrieuc I think that's pretty good idea. Updating now. |
I think this is now in a good state if you want to review, @lukesneeringer. @sbrieuc I'd love if you can give this another test. |
@jonparrott That seems good to me. All my tests are ok |
Great, @lukesneeringer PTAL? |
@lukesneeringer another poke here - this should be ready to merge. |
I'm going to take @lukesneeringer's silence as tacit approval. (I am happy to address concerns in a follow-up PR) |
googleapiclient/http.py
Outdated
@@ -1208,8 +1208,7 @@ def _serialize_request(self, request): | |||
if request.http is not None: | |||
credentials = _auth.get_credentials_from_http(request.http) | |||
if credentials is not None: | |||
if _auth.has_access_token(credentials): |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
Resolves #375 and #350.