Skip to content

Commit

Permalink
Feature: Endpoint Categorization including method (#39)
Browse files Browse the repository at this point in the history
* endpoint now includes method

* standardize on .lower()

---------

Co-authored-by: Steve Bunting <[email protected]>
  • Loading branch information
stevenbunting and Steve Bunting authored Jul 24, 2024
1 parent b29615b commit 21c6eef
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 14 deletions.
6 changes: 5 additions & 1 deletion src/supergood/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ def _should_ignore(
host_domain,
metadata,
url=None,
method=None,
request_body=None,
request_headers=None,
):
Expand All @@ -179,6 +180,7 @@ def _should_ignore(
vendor, endpoint = get_vendor_endpoint_from_config(
self.remote_config,
url=url,
method=method,
request_body=request_body,
request_headers=request_headers,
)
Expand All @@ -200,10 +202,12 @@ def _cache_request(self, request_id, url, method, body, headers):
) # sometimes headers is not json serializable
request["metadata"] = {}
# Check that we should cache the request
parsed_method = safe_decode(method)
if not self._should_ignore(
host_domain,
request["metadata"], # we store endpoint id in metadata
url=url,
method=parsed_method,
request_body=body,
request_headers=safe_headers,
):
Expand All @@ -221,7 +225,7 @@ def _cache_request(self, request_id, url, method, body, headers):
)
request["request"] = {
"id": request_id,
"method": safe_decode(method),
"method": parsed_method,
"url": url,
"body": filtered_body,
"headers": filtered_headers,
Expand Down
1 change: 1 addition & 0 deletions src/supergood/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,7 @@ def redact_values(input_array, remote_config, base_config):
_, endpoint = get_vendor_endpoint_from_config(
remote_config,
url=data["request"].get("url"),
method=data["request"].get("method"),
request_body=data["request"]["body"],
request_headers=data["request"]["headers"],
)
Expand Down
29 changes: 17 additions & 12 deletions src/supergood/remote_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class EndpointConfiguration:
"""

endpoint_id: str
method: str
regex: re.Pattern
location: str
action: str
Expand Down Expand Up @@ -79,6 +80,7 @@ def get_endpoint_test_val(
def get_vendor_endpoint_from_config(
remote_config,
url=None,
method=None,
request_body=None,
request_headers=None,
) -> Tuple[Union[None, VendorConfiguration], Union[None, EndpointConfiguration]]:
Expand All @@ -94,20 +96,22 @@ def get_vendor_endpoint_from_config(
vendor_config = next(
(vcfg for vcfg in remote_config.values() if vcfg.domain in search), None
)
compare_method = method.lower() if method else None

def match(endpoint):
test_method = endpoint.method.lower() if endpoint.method else None
return test_method == compare_method and endpoint.regex.search(
get_endpoint_test_val(
location=endpoint.location,
url=url,
request_body=request_body,
request_headers=request_headers,
)
)

if vendor_config:
return vendor_config, next(
(
ep
for ep in vendor_config.endpoints.values()
if ep.regex.search(
get_endpoint_test_val(
location=ep.location,
url=url,
request_body=request_body,
request_headers=request_headers,
)
)
),
(ep for ep in vendor_config.endpoints.values() if match(ep)),
None,
)
else:
Expand Down Expand Up @@ -141,6 +145,7 @@ def parse_remote_config_json(
endpoints.append(
EndpointConfiguration(
endpoint.get("id"),
endpoint.get("method"),
regex,
matchingRegex.get("location"),
action,
Expand Down
39 changes: 39 additions & 0 deletions tests/caching/test_method.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import pytest
import requests
from pytest_httpserver import HTTPServer

from supergood.api import Api
from tests.helper import get_remote_config


@pytest.mark.parametrize(
"supergood_client",
[{"remote_config": get_remote_config(action="Ignore", method="POST")}],
indirect=True,
)
class TestMethod:
def test_method_matching(self, httpserver: HTTPServer, supergood_client):
httpserver.expect_request("/200", "POST").respond_with_json(
{
"string": "abc",
}
)
httpserver.expect_request("/200", "GET").respond_with_json(
{
"string": "def",
}
)
response1 = requests.request(
method="post",
url=httpserver.url_for("/200"),
)
# First call is ignored due to matching the ignored POST methods
assert response1.json()["string"] == "abc"
supergood_client.flush_cache()
assert Api.post_events.call_args is None
response2 = requests.request(method="get", url=httpserver.url_for("/200"))
# Second call is cached and flushed because it does not match (i.e. is a new endpoint)
assert response2.json()["string"] == "def"
supergood_client.flush_cache()
args = Api.post_events.call_args[0][0]
assert len(args) == 1
5 changes: 4 additions & 1 deletion tests/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ def build_key(key_path, key_action="REDACT"):
return {"keyPath": key_path, "action": key_action}


def get_remote_config(action="Allow", keys=[], location="path", regex="200"):
def get_remote_config(
action="Allow", keys=[], location="path", regex="200", method="GET"
):
built_keys = list(map(lambda tup: build_key(tup[0], tup[1]), keys))
return [
{
Expand All @@ -39,6 +41,7 @@ def get_remote_config(action="Allow", keys=[], location="path", regex="200"):
"endpoints": [
{
"id": "endpoint-id",
"method": method,
"matchingRegex": {"location": location, "regex": regex},
"endpointConfiguration": {
"action": action,
Expand Down
1 change: 1 addition & 0 deletions tests/test_remote_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ def test_remote_config_parse(self):
assert endpoint_config.location == "path"
assert endpoint_config.action == "Allow"
assert endpoint_config.sensitive_keys == []
assert endpoint_config.method.lower() == "get"

def test_client_ignores_before_config(self, httpserver, supergood_client):
# Not a perfect way of simulating it but good enough
Expand Down

0 comments on commit 21c6eef

Please sign in to comment.