1

I have a website running Django 1.8.x on Debian 8.1 with Python 2.7.9. The website or the machine IS NOT under heavy load.

The website does some API call with "drive/v2" and "admin/directory_v1" (servicename/version). Exactly what the website does often is calling files.insert, files.patch, files.move_to_trash or the members.list

All have be running OK in the last 5-6 months with no problem. Note: Google released "drive/v3" on last december. Problems started occuring about one week ago.

First I got some sporadic SSL Timeout Error on some (any) API call. Then I started to get more and more errors. At one point seemed to be persistent, that is once the problem occured for one call, then it occured for any call of all calls. Only the "files.move_to_trash" seemed not be involved except for some sporadic ones.

No modifications were recently made to my website.

I tried to update the "google-api-python-client" library doing

pip install --upgrade google-api-python-client

getting no improvements.

In the next days I noticed that the persistent errors went on for hours then suddenly stopped and all things started working again with few sporadic errors and then starting again with persistent errors. Intermittent operation.

In a different machine I use just for "demo" I got some sporadic error too I never got before.

Something I think really important: I get the timeout errors immediately when doing the API call. That is it's strange to be a real timeout.

Another thing I tried was to download again the credential JSON file from the google developer console: I noticed a new key "project_id" was added inside the file (that is google did something), anyway nothing changed. I also tried to recreate from zero the credentials, reload the JSON file, deassociate and reassociate the application to google drive, still with no success.

As suggested by google support I also checked that "Allow less secure apps" in the account security settings was OFF.

Here a traceback sample:

'Traceback (most recent call last):
File ".\my_gdrive\\utils\\gdrive.py", line 130, in insert
    filee = self.GDService.service.files().insert(body = body,media_body = media_body).execute()
File "/usr/local/lib/python2.7/dist-packages/oauth2client/util.py", line 140, in positional_wrapper
    return wrapped(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/googleapiclient/http.py", line 694, in execute
    _, body = self.next_chunk(http=http, num_retries=num_retries)
File "/usr/local/lib/python2.7/dist-packages/oauth2client/util.py", line 140, in positional_wrapper
    return wrapped(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/googleapiclient/http.py", line 873, in next_chunk
    headers=headers)
File "/usr/local/lib/python2.7/dist-packages/oauth2client/client.py", line 596, in new_request
    redirections, connection_type)
File "/usr/local/lib/python2.7/dist-packages/httplib2/__init__.py", line 1609, in request
    (response, content) = self._request(conn, authority, uri, request_uri, method, body, headers, redirections, cachekey)
File "/usr/local/lib/python2.7/dist-packages/httplib2/__init__.py", line 1351, in _request
    (response, content) = self._conn_request(conn, request_uri, method, body, headers)
File "/usr/local/lib/python2.7/dist-packages/httplib2/__init__.py", line 1307, in _conn_request
    response = conn.getresponse()
File "/usr/lib/python2.7/httplib.py", line 1073, in getresponse
    response.begin()
File "/usr/lib/python2.7/httplib.py", line 415, in begin
    version, status, reason = self._read_status()
File "/usr/lib/python2.7/httplib.py", line 371, in _read_status
    line = self.fp.readline(_MAXLINE + 1)
File "/usr/lib/python2.7/socket.py", line 476, in readline
    data = self._sock.recv(self._rbufsize)
File "/usr/lib/python2.7/ssl.py", line 714, in recv
    return self.read(buflen)
File "/usr/lib/python2.7/ssl.py", line 608, in read
    v = self._sslobj.read(len or 1024)
SSLError: (\'The read operation timed out\',)

UPDATE: added sample code

from oauth2client.django_orm import CredentialsField
class CredentialsModel(models.Model):
    id = models.OneToOneField(settings.AUTH_USER_MODEL, primary_key=True)
    credential = CredentialsField()

Once logged in, I call una tantum the view named "gpermission" to ask and grant permissions to NA_GDRIVE_SCOPES for the logged (system) user. Then every few minutes the code in "THE CODE" section you can see below is run.

NA_GDRIVE_SCOPES = ['https://www.googleapis.com/auth/drive', 'https://www.googleapis.com/auth/admin.directory.group.member']

from django.conf import settings

from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect

from oauth2client import xsrfutil
from oauth2client.client import flow_from_clientsecrets
from oauth2client.django_orm import Storage

from na_gdrive.models import CredentialsModel

def gdrive_get_credentials(func):

    def decorator(request, *args, **kwargs):

        storage = Storage(CredentialsModel, 'id', request.user, 'credential')
        credential = storage.get()
        if credential is None or credential.invalid:

            # settings.NA_GDRIVE_CLIENT_SECRETS_PATH, name of a file containing the OAuth 2.0 information for this
            # application, including client_id and client_secret, which are found
            # on the API Access tab on the Google APIs
            # Console <http://code.google.com/apis/console>

            FLOW = flow_from_clientsecrets(settings.NA_GDRIVE_CLIENT_SECRETS_PATH,
                                           scope = settings.NA_GDRIVE_SCOPES,
                                           redirect_uri = urlparse.urljoin(settings.DOMAIN_ONLINE, reverse("gdrive_auth_return")))

            FLOW.params['access_type'] = 'offline'
            FLOW.params['approval_prompt'] = 'force' 
            FLOW.params['state'] = xsrfutil.generate_token(settings.SECRET_KEY, request.user) + defs.NA_GDRIVE_AUTHNEXT_SEP + request.GET.get("next", reverse("index"))

            authorize_url = FLOW.step1_get_authorize_url()

            return HttpResponseRedirect(authorize_url)

        return func(request, storage, credential, *args, **kwargs)

    return decorator

######## THE VIEWS ########

@login_required
def auth_return(request): #mapped on reverse("gdrive_auth_return")
    if not xsrfutil.validate_token(settings.SECRET_KEY,
                                   str(request.GET['state'].split(defs.NA_GDRIVE_AUTHNEXT_SEP)[0]), #http://stackoverflow.com/questions/27441567/django-1-7-google-oauth2-token-validation-failure
                                   request.user):
        return HttpResponseBadRequest()

    FLOW = flow_from_clientsecrets(settings.NA_GDRIVE_CLIENT_SECRETS_PATH,
                                   scope = settings.NA_GDRIVE_SCOPES,
                                   redirect_uri = urlparse.urljoin(settings.DOMINIO_ONLINE, reverse("gdrive_auth_return")))

    FLOW.params['access_type'] = 'offline'
    FLOW.params['approval_prompt'] = 'force' #Questa non dovrebbe essere necessaria ma al momento è così che sta funzionando in primaindustria dopo i grossi problemi avuti con google

    credential = FLOW.step2_exchange(request.REQUEST)
    storage = Storage(CredentialsModel, 'id', request.user, 'credential')
    storage.put(credential)

    r_uri = request.GET['state'].split(defs.NA_GDRIVE_AUTHNEXT_SEP)[1]
    return HttpResponseRedirect(r_uri)

#The view I call una tantum to ask/grant permission the first time
#when logged with User.objects.get(email = defs.GDRIVE_SYSTEMUSER_EMAIL)

@login_required
@gdrive_get_credentials
def gpermission(request, storage, credential):
    return HttpResponse("Permissions granted")

######## THE CODE ########

from apiclient.discovery import build
from apiclient import errors
from apiclient import http

user = User.objects.get(email = defs.GDRIVE_SYSTEMUSER_EMAIL)
storage = Storage(CredentialsModel, 'id', user, 'credential')
credential = storage.get()
if credential is None or credential.invalid is True:
    raise Exception, 'Bad GDrive credentials'

httpobj = credential.authorize(httplib2.Http())
service = build("drive", "v2", http = httpobj)

media_body = MediaFileUpload(filename, mimetype = mime_type, resumable = True)
body = {
    'title': title,
    'description': description,
    'mimeType': mime_type,
    'parents' : parents_id
}

try:
    filee = service.files().insert(body = body, media_body = media_body).execute() #This gets time SSL Timeout Error
    return filee
except errors.HttpError, error:
    print 'An error occured: %s' % error
    raise

UPDATE: added extra info

In the last days I opened a python shell where I read the credential object with storage.get() (just once). If I submit files onto google drive from shell (still open) when getting the persistent errors I have no problems.

PyMan
  • 11
  • 2

0 Answers0