diff --git a/dvc_http/__init__.py b/dvc_http/__init__.py index 5afa15a..e68c07c 100644 --- a/dvc_http/__init__.py +++ b/dvc_http/__init__.py @@ -113,19 +113,19 @@ async def get_client( # data blobs. We remove the total timeout, and only limit the time # that is spent when connecting to the remote server and waiting # for new data portions. - connect_timeout = kwargs.get("connect_timeout", self.REQUEST_TIMEOUT) + connect_timeout = kwargs.pop("connect_timeout", self.REQUEST_TIMEOUT) kwargs["timeout"] = aiohttp.ClientTimeout( total=None, connect=connect_timeout, sock_connect=connect_timeout, - sock_read=kwargs.get("read_timeout", self.REQUEST_TIMEOUT), + sock_read=kwargs.pop("read_timeout", self.REQUEST_TIMEOUT), ) kwargs["connector"] = aiohttp.TCPConnector( # Force cleanup of closed SSL transports. # See https://github.com/iterative/dvc/issues/7414 enable_cleanup_closed=True, - ssl=make_context(kwargs.get("ssl_verify")), + ssl=make_context(kwargs.pop("ssl_verify", None)), ) return ReadOnlyRetryClient(**kwargs) diff --git a/dvc_http/tests/test_config.py b/dvc_http/tests/test_config.py new file mode 100644 index 0000000..fe79bcd --- /dev/null +++ b/dvc_http/tests/test_config.py @@ -0,0 +1,96 @@ +import ssl + +from dvc.fs import HTTPFileSystem +from fsspec.asyn import get_loop as get_fsspec_loop +from fsspec.asyn import sync + + +def test_public_auth_method(): + config = { + "url": "http://example.com/", + "path": "file.html", + "user": "", + "password": "", + } + + fs = HTTPFileSystem(**config) + + assert "auth" not in fs.fs_args["client_kwargs"] + assert "headers" not in fs.fs_args + + +def test_basic_auth_method(): + user = "username" + password = "password" + config = { + "url": "http://example.com/", + "path": "file.html", + "auth": "basic", + "user": user, + "password": password, + } + + fs = HTTPFileSystem(**config) + + assert fs.fs_args["client_kwargs"]["auth"].login == user + assert fs.fs_args["client_kwargs"]["auth"].password == password + + +def test_custom_auth_method(): + header = "Custom-Header" + password = "password" + config = { + "url": "http://example.com/", + "path": "file.html", + "auth": "custom", + "custom_auth_header": header, + "password": password, + } + + fs = HTTPFileSystem(**config) + + headers = fs.fs_args["headers"] + assert header in headers + assert headers[header] == password + + +def test_ssl_verify_disable(): + config = { + "url": "http://example.com/", + "path": "file.html", + "ssl_verify": False, + } + + fs = HTTPFileSystem(**config) + session = sync(get_fsspec_loop(), fs.fs.set_session) + + # pylint: disable-next=protected-access + assert not session._client._connector._ssl + + +def test_ssl_verify_custom_cert(mocker): + mocker.patch("ssl.SSLContext.load_verify_locations") + config = { + "url": "http://example.com/", + "path": "file.html", + "ssl_verify": "/path/to/custom/cabundle.pem", + } + + fs = HTTPFileSystem(**config) + session = sync(get_fsspec_loop(), fs.fs.set_session) + + # pylint: disable-next=protected-access + assert isinstance(session._client.connector._ssl, ssl.SSLContext) + + +def test_http_method(): + config = { + "url": "http://example.com/", + "path": "file.html", + } + + fs = HTTPFileSystem(**config, method="PUT") + assert fs.upload_method == "PUT" + + fs = HTTPFileSystem(**config, method="POST") + assert fs.upload_method == "POST"