Skip to content

Commit d308bc4

Browse files
committed
Support GET requests to search
1 parent 6ebcdc0 commit d308bc4

File tree

2 files changed

+117
-4
lines changed

2 files changed

+117
-4
lines changed

src/stac_auth_proxy/handlers/reverse_proxy.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,7 @@ async def proxy_request(self, request: Request, *, stream=False) -> httpx.Respon
8383
request=request,
8484
)
8585
if request.method == "GET":
86-
# query = filters.insert_filter(qs=query, filter=cql_filter)
87-
... # TODO...
86+
query = filters.insert_filter(qs=query, filter=cql_filter)
8887
elif request.method in ["POST", "PUT"]:
8988
body_dict = json.loads(body)
9089
body_filter = body_dict.get("filter")

tests/test_filters_jinja2.py

Lines changed: 116 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -274,5 +274,119 @@ def test_search_post(
274274
output_query == expected_output_query
275275
), "Query should be combined with the filter expression."
276276

277-
# Reset test
278-
mock_upstream.reset_mock()
277+
278+
@pytest.mark.parametrize(
279+
"filter_template_expr, auth_filter, anon_filter",
280+
[
281+
# Simple filter, not templated
282+
[
283+
"(properties.private = false)",
284+
"(properties.private = false)",
285+
"(properties.private = false)",
286+
],
287+
# Simple filter, templated
288+
[
289+
"{{ '(properties.private = false)' if token is none else true }}",
290+
"true",
291+
"(properties.private = false)",
292+
],
293+
# Complex filter, not templated
294+
[
295+
"""{
296+
"op": "=",
297+
"args": [{"property": "private"}, true]
298+
}""",
299+
"""{
300+
"op": "=",
301+
"args": [{"property": "private"}, true]
302+
}""",
303+
"""{
304+
"op": "=",
305+
"args": [{"property": "private"}, true]
306+
}""",
307+
],
308+
# Complex filter, templated
309+
[
310+
"""{{ '{"op": "=", "args": [{"property": "private"}, true]}' if token is none else true }}""",
311+
"true",
312+
"""{"op": "=", "args": [{"property": "private"}, true]}""",
313+
],
314+
],
315+
)
316+
@pytest.mark.parametrize("is_authenticated", [True, False])
317+
@pytest.mark.parametrize(
318+
"input_query",
319+
[
320+
# Not using filter
321+
{
322+
"collections": "example-collection",
323+
"bbox": "160.6,-55.95,-170,-25.89",
324+
"datetime": "2021-06-01T00:00:00Z/2021-06-30T23:59:59Z",
325+
},
326+
# Using filter
327+
# {
328+
# "filter-lang": "cql2-json",
329+
# "filter": {
330+
# "op": "and",
331+
# "args": [
332+
# {"op": "=", "args": [{"property": "collection"}, "landsat-8-l1"]},
333+
# {"op": "<=", "args": [{"property": "eo:cloud_cover"}, 20]},
334+
# {"op": "=", "args": [{"property": "platform"}, "landsat-8"]},
335+
# ],
336+
# },
337+
# "limit": 5,
338+
# },
339+
],
340+
)
341+
def test_search_get(
342+
mock_upstream,
343+
source_api_server,
344+
filter_template_expr,
345+
auth_filter,
346+
anon_filter,
347+
is_authenticated,
348+
input_query,
349+
token_builder,
350+
):
351+
"""Test filter is applied to search with fimple filtering."""
352+
# Setup app
353+
app = app_factory(
354+
upstream_url=source_api_server,
355+
items_filter={
356+
"cls": "stac_auth_proxy.filters.Template",
357+
"args": [filter_template_expr.strip()],
358+
},
359+
default_public=True,
360+
)
361+
362+
# Query API
363+
headers = (
364+
{"Authorization": f"Bearer {token_builder({})}"} if is_authenticated else {}
365+
)
366+
response = TestClient(app, headers=headers).get("/search", params=input_query)
367+
response.raise_for_status()
368+
369+
# Retrieve query from upstream
370+
assert mock_upstream.call_count == 1
371+
[r] = cast(list[Request], mock_upstream.call_args[0])
372+
assert r.read().decode() == ""
373+
upstream_querystring = dict(r.url.params)
374+
375+
# Parse query from upstream
376+
input_filter = input_query.get("filter")
377+
expected_filter = auth_filter if is_authenticated else anon_filter
378+
expected_filter_exprs = [
379+
cql2.Expr(expr).to_text()
380+
for expr in [input_filter, expected_filter.strip()]
381+
if expr
382+
]
383+
384+
# TODO: Use QS, not dict
385+
expected_output_query = {
386+
**input_query,
387+
"filter": cql2.Expr(" AND ".join(expected_filter_exprs)).to_text(),
388+
}
389+
390+
assert (
391+
upstream_querystring == expected_output_query
392+
), "Query should be combined with the filter expression."

0 commit comments

Comments
 (0)