diff --git a/openeo_driver/dummy/dummy_backend.py b/openeo_driver/dummy/dummy_backend.py index d482ebc7..1694b2af 100644 --- a/openeo_driver/dummy/dummy_backend.py +++ b/openeo_driver/dummy/dummy_backend.py @@ -759,6 +759,24 @@ def get_result_assets(self, job_id: str, user_id: str) -> Dict[str, dict]: }, } + elif job_id == "j-24111211111111111111111111111111": + return { + "subfolder/output.tiff": { + "output_dir": f"{self._output_root()}/{job_id}", + "href": f"{self._output_root()}/{job_id}/subfolder/output.tiff", + "type": "image/tiff; application=geotiff", + "roles": ["data"], + "bands": [Band(name="NDVI", common_name="NDVI", wavelength_um=1.23)], + "nodata": 123, + "instruments": "MSI", + "bbox": [0.0, 50.0, 5.0, 55.0], + "geometry": { + "type": "Polygon", + "coordinates": [[[0.0, 50.0], [0.0, 55.0], [5.0, 55.0], [5.0, 50.0], [0.0, 50.0]]], + }, + }, + } + # default return: return { "output.tiff": { "output_dir": f"{self._output_root()}/{job_id}", diff --git a/openeo_driver/views.py b/openeo_driver/views.py index 1d3b0039..5efe8b8f 100644 --- a/openeo_driver/views.py +++ b/openeo_driver/views.py @@ -1448,13 +1448,13 @@ def _asset_object(job_id, user_id, filename: str, asset_metadata: dict, job_info return result_dict @api_endpoint - @blueprint.route('/jobs//results/assets/', methods=['GET']) + @blueprint.route("/jobs//results/assets/", methods=["GET"]) @auth_handler.requires_bearer_auth def download_job_result(job_id, filename, user: User): return _download_job_result(job_id=job_id, filename=filename, user_id=user.user_id) @api_endpoint - @blueprint.route('/jobs//results/assets///', methods=['GET']) + @blueprint.route("/jobs//results/assets///", methods=["GET"]) def download_job_result_signed(job_id, user_base64, secure_key, filename): expires = request.args.get('expires') signer = get_backend_config().url_signer diff --git a/tests/test_views.py b/tests/test_views.py index 683bd6e5..c2b21d0c 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -1209,6 +1209,14 @@ def _fresh_job_registry(next_job_id="job-1234", output_root: Optional[Path] = No start_datetime=None, end_datetime=None, ), + (TEST_USER, "j-24111211111111111111111111111111"): BatchJobMetadata( + id="j-24111211111111111111111111111111", + status="finished", + created=datetime(2024, 11, 12, 12, 16, 34), + bbox=[34.456156, -0.910085, 34.796396, -0.345477], + start_datetime=None, + end_datetime=None, + ), } dummy_backend.DummyBatchJobs._job_result_registry = {} @@ -1399,6 +1407,12 @@ def test_list_user_jobs_100(self, api100): "status": "finished", "progress": 100, "created": "2024-08-30T12:16:34Z", + }, + { + "id": "j-24111211111111111111111111111111", + "status": "finished", + "progress": 100, + "created": "2024-11-12T12:16:34Z", } ], "links": [] @@ -2537,6 +2551,21 @@ def test_download_result(self, api, tmp_path): assert resp.assert_status_code(200).data == b"tiffdata" assert resp.headers["Content-Type"] == "image/tiff; application=geotiff" + def test_download_result_nested_path(self, api110, tmp_path): + output_root = Path(tmp_path) + jobs = {"j-24111211111111111111111111111111": {"status": "finished"}} + with self._fresh_job_registry(output_root=output_root, jobs=jobs): + output = output_root / "j-24111211111111111111111111111111/subfolder/output.tiff" + output.parent.mkdir(parents=True) + with output.open("wb") as f: + f.write(b"tiffdata") + resp = api110.get( + "/jobs/j-24111211111111111111111111111111/results/assets/subfolder/output.tiff", + headers=self.AUTH_HEADER, + ) + assert resp.assert_status_code(200).data == b"tiffdata" + assert resp.headers["Content-Type"] == "image/tiff; application=geotiff" + def test_download_result_vectorcube(self, api, tmp_path): output_root = Path(tmp_path) job_id = "07024ee9-7847-4b8a-b260-6c879a2b3cdc"