Repository: celery/kombu

Issue:
No proxy support using SQS
The async HTTP code is not allowing the proxy environment variables to be used by libcurl

It seems to be due to this code in `async/http/curl.py`

```
        if request.proxy_host:
            if not request.proxy_port:
                raise ValueError('Request with proxy_host but no proxy_port')
            setopt(_pycurl.PROXY, request.proxy_host)
            setopt(_pycurl.PROXYPORT, request.proxy_port)
            if request.proxy_username:
                setopt(_pycurl.PROXYUSERPWD, '{0}:{1}'.format(
                    request.proxy_username, request.proxy_password or ''))
        else:
            setopt(_pycurl.PROXY, '')
            curl.unsetopt(_pycurl.PROXYUSERPWD)
```
Notice that if the original request does not specify a `proxy_host` then it actually sets it to empty in the curl OPTs which makes libcurl NOT read the environment for it either.

And the caller in this case is the SQS transport which does NOT pass any proxy setting in either so when using SQS there doesn't appear to be a way to make Kombu use a proxy for the async HTTP. 

(Note: The calls through Boto DO work because Boto reads it from the environment variables by default)


Discussion:

Resolving patch:
diff --git a/kombu/asynchronous/http/curl.py b/kombu/asynchronous/http/curl.py
--- a/kombu/asynchronous/http/curl.py
+++ b/kombu/asynchronous/http/curl.py
@@ -231,9 +231,6 @@ def _setup_request(self, curl, request, buffer, headers, _pycurl=pycurl):
             if request.proxy_username:
                 setopt(_pycurl.PROXYUSERPWD, '{}:{}'.format(
                     request.proxy_username, request.proxy_password or ''))
-        else:
-            setopt(_pycurl.PROXY, '')
-            curl.unsetopt(_pycurl.PROXYUSERPWD)
 
         setopt(_pycurl.SSL_VERIFYPEER, 1 if request.validate_cert else 0)
         setopt(_pycurl.SSL_VERIFYHOST, 2 if request.validate_cert else 0)


Test patch:
diff --git a/t/unit/asynchronous/http/test_curl.py b/t/unit/asynchronous/http/test_curl.py
--- a/t/unit/asynchronous/http/test_curl.py
+++ b/t/unit/asynchronous/http/test_curl.py
@@ -1,4 +1,5 @@
-from unittest.mock import Mock, call, patch
+from io import BytesIO
+from unittest.mock import ANY, Mock, call, patch
 
 import pytest
 
@@ -131,3 +132,24 @@ def test_on_readable_on_writeable(self):
             x._on_event.assert_called_with(fd, _pycurl.CSELECT_IN)
             x.on_writable(fd, _pycurl=_pycurl)
             x._on_event.assert_called_with(fd, _pycurl.CSELECT_OUT)
+
+    def test_setup_request_sets_proxy_when_specified(self):
+        with patch('kombu.asynchronous.http.curl.pycurl') as _pycurl:
+            x = self.Client()
+            proxy_host = 'http://www.example.com'
+            request = Mock(
+                name='request', headers={}, auth_mode=None, proxy_host=None
+            )
+            proxied_request = Mock(
+                name='request', headers={}, auth_mode=None,
+                proxy_host=proxy_host, proxy_port=123
+            )
+            x._setup_request(
+                x.Curl, request, BytesIO(), x.Headers(), _pycurl=_pycurl
+            )
+            with pytest.raises(AssertionError):
+                x.Curl.setopt.assert_any_call(_pycurl.PROXY, ANY)
+            x._setup_request(
+                x.Curl, proxied_request, BytesIO(), x.Headers(), _pycurl
+            )
+            x.Curl.setopt.assert_any_call(_pycurl.PROXY, proxy_host)