From 355eb521644d6a65884eba67251d3c7e8fd4ae52 Mon Sep 17 00:00:00 2001 From: Xiao Gui Date: Mon, 13 Jul 2026 12:15:31 +0200 Subject: [PATCH] fix: http head sometimes return 405 --- src/neuroglancer_scripts/http_accessor.py | 4 ++++ src/neuroglancer_scripts/sharded_http_accessor.py | 6 +++++- unit_tests/test_http_accessor.py | 9 +++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/neuroglancer_scripts/http_accessor.py b/src/neuroglancer_scripts/http_accessor.py index da423a4..931e21a 100644 --- a/src/neuroglancer_scripts/http_accessor.py +++ b/src/neuroglancer_scripts/http_accessor.py @@ -59,6 +59,10 @@ def file_exists(self, relative_path): r = self._session.head(file_url) if r.status_code == requests.codes.not_found: return False + if r.status_code == 405: + r = self._session.get(file_url, stream=True) + r.raise_for_status() + return True r.raise_for_status() except requests.exceptions.RequestException as exc: raise DataAccessError("Error probing the existence of " diff --git a/src/neuroglancer_scripts/sharded_http_accessor.py b/src/neuroglancer_scripts/sharded_http_accessor.py index 72a383c..4a8f55e 100644 --- a/src/neuroglancer_scripts/sharded_http_accessor.py +++ b/src/neuroglancer_scripts/sharded_http_accessor.py @@ -40,9 +40,13 @@ def __init__(self, base_url, session: requests.Session, assert self.can_read_cmc def file_exists(self, filepath): - resp = self._session.head(f"{self.base_url}{filepath}") + url = f"{self.base_url}{filepath}" + resp = self._session.head(url) if resp.status_code in (200, 404): return resp.status_code == 200 + if resp.status_code == 405: + resp = self._session.get(url, stream=True) + return resp.status_code == 200 resp.raise_for_status() return False diff --git a/unit_tests/test_http_accessor.py b/unit_tests/test_http_accessor.py index 43b5de5..2771650 100644 --- a/unit_tests/test_http_accessor.py +++ b/unit_tests/test_http_accessor.py @@ -33,6 +33,10 @@ def test_http_accessor(base_url, requests_mock): requests_mock.head("http://h.test/i/info", status_code=404) assert a.file_exists("info") is False + requests_mock.head("http://h.test/i/info", status_code=405) + requests_mock.get("http://h.test/i/info", status_code=200) + assert a.file_exists("info") is True + requests_mock.get("http://h.test/i/key/0-1_0-1_0-1", content=dummy_chunk_buf) fetched_chunk = a.fetch_chunk("key", chunk_coords) @@ -47,6 +51,11 @@ def test_http_accessor_errors(requests_mock): with pytest.raises(DataAccessError): a.file_exists("info") + requests_mock.head("http://h.test/i/info", status_code=405) + requests_mock.get("http://h.test/i/info", status_code=404) + with pytest.raises(DataAccessError): + a.file_exists("info") + requests_mock.get("http://h.test/i/info", status_code=404) with pytest.raises(DataAccessError): a.fetch_file("info")