This is an automated email from the ASF dual-hosted git repository.

ash pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/master by this push:
     new ca432ee  HttpHook: Use request factory and respect defaults (#14701)
ca432ee is described below

commit ca432eebdfa625ea45219ed0d73aef30d2854325
Author: Nick Garanko <[email protected]>
AuthorDate: Tue May 4 18:22:37 2021 +0200

    HttpHook: Use request factory and respect defaults (#14701)
    
    Use Request's session.request factory for HTTP request initiation, this 
will use
    environment variables and sensible defaults for requests.
    
    Also use verify option only if it is provided to run method, as requests 
library
    already defaults to True.
    
    Our organization uses firewalls and custom SSL certificates to communicate
    between systems, this can be achieved via `CURL_CA_BUNDLE` and
    `REQUESTS_CA_BUNDLE` environment variables.  Requests library takes both 
into
    account and uses them as default value for verify option when sending 
request to
    remote system.
    
    Current implementation is setting verify to True, which overwrites defaults 
and
    as results requests can not be made due to SSL verification issues. This PR 
is
    fixing the problem.
---
 airflow/providers/http/hooks/http.py      | 25 +++++++----
 tests/providers/http/hooks/test_http.py   | 74 +++++++++++++++++++++++++++++++
 tests/providers/http/sensors/test_http.py |  3 ++
 3 files changed, 93 insertions(+), 9 deletions(-)

diff --git a/airflow/providers/http/hooks/http.py 
b/airflow/providers/http/hooks/http.py
index 542a620..6cf5f8e 100644
--- a/airflow/providers/http/hooks/http.py
+++ b/airflow/providers/http/hooks/http.py
@@ -176,16 +176,23 @@ class HttpHook(BaseHook):
         """
         extra_options = extra_options or {}
 
+        settings = session.merge_environment_settings(
+            prepped_request.url,
+            proxies=extra_options.get("proxies", {}),
+            stream=extra_options.get("stream", False),
+            verify=extra_options.get("verify"),
+            cert=extra_options.get("cert"),
+        )
+
+        # Send the request.
+        send_kwargs = {
+            "timeout": extra_options.get("timeout"),
+            "allow_redirects": extra_options.get("allow_redirects", True),
+        }
+        send_kwargs.update(settings)
+
         try:
-            response = session.send(
-                prepped_request,
-                stream=extra_options.get("stream", False),
-                verify=extra_options.get("verify", True),
-                proxies=extra_options.get("proxies", {}),
-                cert=extra_options.get("cert"),
-                timeout=extra_options.get("timeout"),
-                allow_redirects=extra_options.get("allow_redirects", True),
-            )
+            response = session.send(prepped_request, **send_kwargs)
 
             if extra_options.get('check_response', True):
                 self.check_response(response)
diff --git a/tests/providers/http/hooks/test_http.py 
b/tests/providers/http/hooks/test_http.py
index 816adc3..825847b 100644
--- a/tests/providers/http/hooks/test_http.py
+++ b/tests/providers/http/hooks/test_http.py
@@ -16,7 +16,9 @@
 # specific language governing permissions and limitations
 # under the License.
 import json
+import os
 import unittest
+from collections import OrderedDict
 from unittest import mock
 
 import pytest
@@ -279,5 +281,77 @@ class TestHttpHook(unittest.TestCase):
             # will raise NoMockAddress exception if obj1 != request.json()
             HttpHook(method=method).run('v1/test', json=obj1)
 
+    @mock.patch('airflow.providers.http.hooks.http.requests.Session.send')
+    def test_verify_set_to_true_by_default(self, mock_session_send):
+        with mock.patch(
+            'airflow.hooks.base.BaseHook.get_connection', 
side_effect=get_airflow_connection_with_port
+        ):
+            self.get_hook.run('/some/endpoint')
+            mock_session_send.assert_called_once_with(
+                mock.ANY,
+                allow_redirects=True,
+                cert=None,
+                proxies=OrderedDict(),
+                stream=False,
+                timeout=None,
+                verify=True,
+            )
+
+    @mock.patch('airflow.providers.http.hooks.http.requests.Session.send')
+    @mock.patch.dict(os.environ, {"REQUESTS_CA_BUNDLE": "/tmp/test.crt"})
+    def test_requests_ca_bundle_env_var(self, mock_session_send):
+        with mock.patch(
+            'airflow.hooks.base.BaseHook.get_connection', 
side_effect=get_airflow_connection_with_port
+        ):
+
+            self.get_hook.run('/some/endpoint')
+
+            mock_session_send.assert_called_once_with(
+                mock.ANY,
+                allow_redirects=True,
+                cert=None,
+                proxies=OrderedDict(),
+                stream=False,
+                timeout=None,
+                verify='/tmp/test.crt',
+            )
+
+    @mock.patch('airflow.providers.http.hooks.http.requests.Session.send')
+    @mock.patch.dict(os.environ, {"REQUESTS_CA_BUNDLE": "/tmp/test.crt"})
+    def test_verify_respects_requests_ca_bundle_env_var(self, 
mock_session_send):
+        with mock.patch(
+            'airflow.hooks.base.BaseHook.get_connection', 
side_effect=get_airflow_connection_with_port
+        ):
+
+            self.get_hook.run('/some/endpoint', extra_options={'verify': True})
+
+            mock_session_send.assert_called_once_with(
+                mock.ANY,
+                allow_redirects=True,
+                cert=None,
+                proxies=OrderedDict(),
+                stream=False,
+                timeout=None,
+                verify='/tmp/test.crt',
+            )
+
+    @mock.patch('airflow.providers.http.hooks.http.requests.Session.send')
+    @mock.patch.dict(os.environ, {"REQUESTS_CA_BUNDLE": "/tmp/test.crt"})
+    def 
test_verify_false_parameter_overwrites_set_requests_ca_bundle_env_var(self, 
mock_session_send):
+        with mock.patch(
+            'airflow.hooks.base.BaseHook.get_connection', 
side_effect=get_airflow_connection_with_port
+        ):
+            self.get_hook.run('/some/endpoint', extra_options={'verify': 
False})
+
+            mock_session_send.assert_called_once_with(
+                mock.ANY,
+                allow_redirects=True,
+                cert=None,
+                proxies=OrderedDict(),
+                stream=False,
+                timeout=None,
+                verify=False,
+            )
+
 
 send_email_test = mock.Mock()
diff --git a/tests/providers/http/sensors/test_http.py 
b/tests/providers/http/sensors/test_http.py
index 569d235..811a0eb 100644
--- a/tests/providers/http/sensors/test_http.py
+++ b/tests/providers/http/sensors/test_http.py
@@ -201,6 +201,9 @@ class FakeSession:
             self.response._content += ('/' + 
request.params['date']).encode('ascii', 'ignore')
         return self.response
 
+    def merge_environment_settings(self, _url, **kwargs):
+        return kwargs
+
 
 class TestHttpOpSensor(unittest.TestCase):
     def setUp(self):

Reply via email to