Unify hash request validation

This commit is contained in:
Dariusz L
2026-08-03 14:15:00 +02:00
parent cf08aa97de
commit 7cba340de1
2 changed files with 58 additions and 27 deletions
+24 -27
View File
@@ -376,6 +376,20 @@ class HashService:
return "", "file is outside configured model directories"
return normalized_path, ""
async def _get_validated_hash_file_request(self, request):
"""Read and validate the file request shared by hash endpoints."""
data = await request.json()
normalized_path, error = self.resolve_hash_file_request(data)
if not error:
return normalized_path, None
status = 400 if error == "file_path is required" else (
403
if error == "file is outside configured model directories"
else 404
)
return "", self.web.json_response({"error": error}, status=status)
def write_calculated_hash_metadata(
self,
normalized_path,
@@ -545,20 +559,11 @@ class HashService:
async def calculate_file_hash(self, request):
"""Calculate SHA256 for a local model and persist sidecar metadata."""
data = await request.json()
normalized_path, error = self.resolve_hash_file_request(data)
if error == "file_path is required":
return self.web.json_response(
{"error": "file_path is required"}, status=400
)
if error:
status = (
403
if error == "file is outside configured model directories"
else 404
)
return self.web.json_response({"error": error}, status=status)
normalized_path, error_response = await self._get_validated_hash_file_request(
request
)
if error_response:
return error_response
sha256, sha256_source = self.calculate_sha256_with_progress(normalized_path)
if not sha256:
@@ -587,19 +592,11 @@ class HashService:
async def calculate_file_hash_start(self, request):
"""Start SHA256 calculation in a background thread."""
data = await request.json()
normalized_path, error = self.resolve_hash_file_request(data)
if error == "file_path is required":
return self.web.json_response(
{"error": "file_path is required"}, status=400
)
if error:
status = (
403
if error == "file is outside configured model directories"
else 404
)
return self.web.json_response({"error": error}, status=status)
normalized_path, error_response = await self._get_validated_hash_file_request(
request
)
if error_response:
return error_response
self.hash_tracker.cleanup()
progress_id = f"hash_{uuid.uuid4().hex}"
+34
View File
@@ -411,6 +411,40 @@ async def test_calculate_file_hash_writes_metadata_and_reports_source():
assert written["metadata"]["file_name"] == "old"
@pytest.mark.asyncio
@pytest.mark.parametrize(
"route",
[
"/model_resolver/calculate-file-hash",
"/model_resolver/calculate-file-hash/start",
],
)
async def test_hash_calculation_routes_share_file_request_validation(route):
handlers, values = _build_hash_routes()
handler = handlers[("POST", route)]
response = await handler(_request({}))
assert response.status == 400
assert json.loads(response.text) == {"error": "file_path is required"}
with tempfile.TemporaryDirectory() as temp_dir:
missing_path = os.path.join(temp_dir, "missing.safetensors")
response = await handler(_request({"file_path": missing_path}))
assert response.status == 404
assert json.loads(response.text) == {"error": "file does not exist"}
outside_path = os.path.join(temp_dir, "outside.safetensors")
with open(outside_path, "wb") as model_file:
model_file.write(b"model")
values["is_path_in_configured_model_roots"].return_value = False
response = await handler(_request({"file_path": outside_path}))
assert response.status == 403
assert json.loads(response.text) == {
"error": "file is outside configured model directories"
}
def test_hash_service_reports_header_source_and_cancellation():
sha256 = "e" * 64
_, values = _build_hash_routes()