question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Thread safe of httplib2 and credentials -> update Documentation

See original GitHub issue

So right now I’m using your library with multiple threads. Due to the fact that httplib2 is not thread safe I tried to use your examples.

# Create a new Http() object for every request
def build_request(http, *args, **kwargs):
  new_http = httplib2.Http()
  return apiclient.http.HttpRequest(new_http, *args, **kwargs)
service = build('api_name', 'api_version', requestBuilder=build_request)

# Pass in a new Http() manually for every request
service = build('api_name', 'api_version')
http = httplib2.Http()
service.stamps().list().execute(http=http)

But either way I have the problem that the threads are not authenticated. In the documentation is nothing like this mentioned. I tried just building an own httplib2.Http() object for every thread at the beginning of it and also tried the approach of overriding the default requestBuilder of the service which I used across all threads but nothing worked due to authentification issues.

In the end it worked for me that I just executed the following authenticate_and_build_service() function for every thread. This function basically return a new service object via the build('drive', 'v3', credentials=creds).

def authenticate_and_build_service():
    # If modifying these scopes, delete the file server_token.pickle.
    scopes = ['https://www.googleapis.com/auth/drive']

    creds = None
    # The file server_token.pickle stores the user's access and refresh tokens, and is
    # created automatically when the authorization flow completes for the first
    # time.
    if os.path.exists('server_token.pickle'):
        with open('server_token.pickle', 'rb') as token:
            creds = pickle.load(token)
    # If there are no (valid) credentials available, let the user log in.
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                'server_credentials.json', scopes)
            creds = flow.run_local_server(port=0)
        # Save the credentials for the next run
        with open('server_token.pickle', 'wb') as token:
            pickle.dump(creds, token)

    return build('drive', 'v3', credentials=creds)

Nevertheless I’m not sure if it has any downsides of building a service object for every thread and it would be nice if someone could comment on this and maybe even update the documentation.

I also didn’t find a way in the execute() function to specify credentials.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:1
  • Comments:5 (1 by maintainers)

github_iconTop GitHub Comments

3reactions
busunkim96commented, Jan 22, 2020

@DopeforHope Thanks for the detailed report! It looks like our docs need to be updated to explain how to authorize the httplib2 instances.

0reactions
hendolimcommented, Jun 23, 2020

After digging up the source code, I found this in _auth.py:

def authorized_http(credentials):
    """Returns an http client that is authorized with the given credentials.

    Args:
        credentials (Union[
            google.auth.credentials.Credentials,
            oauth2client.client.Credentials]): The credentials to use.

    Returns:
        Union[httplib2.Http, google_auth_httplib2.AuthorizedHttp]: An
            authorized http client.
    """
    from googleapiclient.http import build_http

    if HAS_GOOGLE_AUTH and isinstance(credentials, google.auth.credentials.Credentials):
        if google_auth_httplib2 is None:
            raise ValueError(
                "Credentials from google.auth specified, but "
                "google-api-python-client is unable to use these credentials "
                "unless google-auth-httplib2 is installed. Please install "
                "google-auth-httplib2."
            )
        return google_auth_httplib2.AuthorizedHttp(credentials, http=build_http())
    else:
        return credentials.authorize(build_http())

So I think I can just do something like this:

new_http_client = httplib2.Http()
authorized_htpp = google_auth_httplib2.AuthorizedHttp(credentials, http=new_http_client)
gcpservice.execute(http=authorized_htpp)

UPDATE: This works for me. Although I’d still love to hear from google engineers if this is a recommended approach

Read more comments on GitHub >

github_iconTop Results From Across the Web

httplib2 A comprehensive HTTP client library.
This implements Section 3.2 of Detecting the Lost Update Problem Using Unreserved Checkout. The httplib2 module defines the following variables:.
Read more >
Thread Safety | google-api-python-client
This page contains important information about the thread safety of this library. The httplib2.Http() objects are not thread-safe. The google-api-python-client ...
Read more >
Are urllib2 and httplib thread safe? - python - Stack Overflow
I suggest using httplib2 or urllib3 as an alternative if thread-safety is required. Generally, if a module's documentation does not mention ...
Read more >
pydrive2 package - PyDrive2 1.14.0 documentation - Iterative.ai
Provides changed metadata elements to efficiently update api resources. ... Create and authorize an httplib2.Http object. Necessary for thread-safety.
Read more >
oauth2client deprecation — google-auth 2.9.0 documentation
Lack of a secure, thread-safe, and modern transport: oauth2client is inextricably dependent on httplib2. httplib2 is largely unmaintained (although recently ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found