Forums

Connecting to Dropbox using the API fails w/ConnectionRefusedError

I get a strange message when I try to use the minimal Dropbox API. The code is following:

import dropbox
access_token = <got it when registering an application at https://www.dropbox.com/developers/apps/info>
api_client = dropbox.client.DropboxClient(access_token)
print(api_client.account_info())

When I run this code the following exception occure:

File "/home/maxint/.local/lib/python3.4/site-packages/urllib3/util/retry.py", line 265, in increment raise MaxRetryError(_pool, url, error)
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='api.dropbox.com', port=443): Max retries exceeded with url: /1/account/info (Caused by ProtocolError('Connection aborted.', ConnectionRefusedError(111, 'Connection refused')))

How can I fix tihs problem?

[edit by admin: formatting]

Hm. It's possible that dropbox have changed the subdomain they're serving their api from. I'll open all subdomains on the proxy -- try again?

If that doesn't work, then the next thing to check would be, have you definitely got your access token correct?

Thanks for taking a look into it!

I just re-run my code - the results are identical. It is possible but pretty difficult for me to make a mistake copy-pasting the access_token from a web-site - but I double-checked - the code runs fine on a local machine.

What do you think I should check next?

Looking at the error closer, it looks like the Dropbox API is ignoring the proxy settings for your free account. Free PythonAnywhere accounts access the external Internet using a proxy so that we can stop spammers and hackers from using our site to cause trouble, and we put the details of the proxy into your code's environment so that libraries know to connect using it. Most libraries use those settings, but some don't.

Could you give us the full stacktrace? As you've installed the Dropbox API with pip install --user (to judge from the part of the trace you give above) it may be that we can tell you how to patch their code so that it behaves itself...

Sure, see the full stacktrace attached. Thanks for your time!

13:51 ~/sleeping $ python3.4 db.py 
Traceback (most recent call last):
  File "/home/maxint/.local/lib/python3.4/site-packages/urllib3/connectionpool.py", line 516, in urlopen
    body=body, headers=headers)
  File "/home/maxint/.local/lib/python3.4/site-packages/urllib3/connectionpool.py", line 304, in _make_request
    self._validate_conn(conn)
  File "/home/maxint/.local/lib/python3.4/site-packages/urllib3/connectionpool.py", line 722, in _validate_conn
    conn.connect()
  File "/home/maxint/.local/lib/python3.4/site-packages/urllib3/connection.py", line 203, in connect
    conn = self._new_conn()
  File "/home/maxint/.local/lib/python3.4/site-packages/urllib3/connection.py", line 133, in _new_conn
    (self.host, self.port), self.timeout, **extra_kw)
  File "/home/maxint/.local/lib/python3.4/site-packages/urllib3/util/connection.py", line 87, in create_connection
    raise err
  File "/home/maxint/.local/lib/python3.4/site-packages/urllib3/util/connection.py", line 78, in create_connection
    sock.connect(sa)
ConnectionRefusedError: [Errno 111] Connection refused

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "db.py", line 7, in <module>
    print(api_client.account_info())
  File "/home/maxint/.local/lib/python3.4/site-packages/dropbox/client.py", line 149, in account_info
    return self.rest_client.GET(url, headers)
  File "/home/maxint/.local/lib/python3.4/site-packages/dropbox/rest.py", line 311, in GET
    return cls.IMPL.GET(*n, **kw)
  File "/home/maxint/.local/lib/python3.4/site-packages/dropbox/rest.py", line 246, in GET
    return self.request("GET", url, headers=headers, raw_response=raw_response)
  File "/home/maxint/.local/lib/python3.4/site-packages/dropbox/rest.py", line 218, in request
    preload_content=False
  File "/home/maxint/.local/lib/python3.4/site-packages/urllib3/poolmanager.py", line 153, in urlopen
    response = conn.urlopen(method, u.request_uri, **kw)
  File "/home/maxint/.local/lib/python3.4/site-packages/urllib3/connectionpool.py", line 579, in urlopen
    release_conn=release_conn, **response_kw)
  File "/home/maxint/.local/lib/python3.4/site-packages/urllib3/connectionpool.py", line 579, in urlopen
    release_conn=release_conn, **response_kw)
  File "/home/maxint/.local/lib/python3.4/site-packages/urllib3/connectionpool.py", line 579, in urlopen
    release_conn=release_conn, **response_kw)
  File "/home/maxint/.local/lib/python3.4/site-packages/urllib3/connectionpool.py", line 559, in urlopen
    _pool=self, _stacktrace=stacktrace)
  File "/home/maxint/.local/lib/python3.4/site-packages/urllib3/util/retry.py", line 265, in increment
    raise MaxRetryError(_pool, url, error)
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='api.dropbox.com', port=443): Max retries exceeded with url: /1/account/info (Caused by ProtocolError('Connection aborted.', Connect
ionRefusedError(111, 'Connection refused')))
22:22 ~/sleeping $

[edited by admin: formatting]

OK. I think that if you edit the file rest.py in your Dropbox library, and change this bit:

    self.pool_manager = urllib3.PoolManager(
        num_pools=4, # only a handful of hosts. api.dropbox.com, api-content.dropbox.com
        maxsize=max_reusable_connections,
        block=False,
        timeout=60.0, # long enough so datastores await doesn't get interrupted
        cert_reqs=ssl.CERT_REQUIRED,
        ca_certs=TRUSTED_CERT_FILE,
        ssl_version=ssl.PROTOCOL_TLSv1,
    )

...to this:

    self.pool_manager = urllib3.ProxyManager(
        "http://proxy.server:3128",
        num_pools=4, # only a handful of hosts. api.dropbox.com, api-content.dropbox.com
        maxsize=max_reusable_connections,
        block=False,
        timeout=60.0, # long enough so datastores await doesn't get interrupted
        cert_reqs=ssl.CERT_REQUIRED,
        ca_certs=TRUSTED_CERT_FILE,
        ssl_version=ssl.PROTOCOL_TLSv1,
    )

...then it should work. Let me know if it does (or if it doesn't :-) and perhaps we can suggest a patch to the Dropbox API guys.

Something is wrong. I've double-checked, but can't understand the problem. The corrected code doesn't run with the following error:

Traceback (most recent call last):
  File "db.py", line 1, in <module>
    import dropbox
  File "/home/maxint/.local/lib/python3.4/site-packages/dropbox/__init__.py", line 3, in <module>
    from . import client, rest, session
  File "/home/maxint/.local/lib/python3.4/site-packages/dropbox/client.py", line 22, in <module>
    from .rest import ErrorResponse, RESTClient, params_to_urlencoded
  File "/home/maxint/.local/lib/python3.4/site-packages/dropbox/rest.py", line 262, in <module>
    class RESTClient(object):
  File "/home/maxint/.local/lib/python3.4/site-packages/dropbox/rest.py", line 269, in RESTClient
    IMPL = RESTClientObject()
  File "/home/maxint/.local/lib/python3.4/site-packages/dropbox/rest.py", line 183, in __init__
    ssl_version=ssl.PROTOCOL_TLSv1,
TypeError: __init__() got multiple values for argument 'num_pools'

And I'm 100% sure I have the the exact change you requested - added "http://proxy.server:3128" as the first parameter. What's I'm missing?

[edit by admin: formatting]

Did you change the class name as well, from PoolManager to ProxyManager? (I can see that our syntax highlighting made the proxy setting red, which could well have misled you into thinking that it was the only change -- it's actually just because the syntax highlighter makes all strings red.)

I'm sorry - the hour were wrong for me to do the changes ;) the code you've provided just works!!! Thank you so much!

Excellent, thanks for confirming that! I'll see if we can put a patch together for the Dropbox API team.

...patch submitted.

This really helped me too, thanks! giles, do you have a ticket number for the Dropbox patch?

Oddly enough, I can't find a ticket number anywhere. I think maybe we submitted it via a support request on Dropbox's website, but I don't see any record of a reply :-(