Skip to content
This repository was archived by the owner on Feb 18, 2026. It is now read-only.

Commit b72df8a

Browse files
committed
Fix obfuscation plugin config lookup and request state handling
- Use short name "obfuscate_tags" for config lookup to match config.yaml - Handle None config values with `(context.get("config") or {})` - Add state property to RequestAdapter for header modifications check - Check request.state.header_modifications in should_obfuscate_private_tags - Update migration test default ports to 9000 and add obfuscation tests
1 parent 1e0f900 commit b72df8a

6 files changed

Lines changed: 69 additions & 6 deletions

File tree

gsrest/app.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -444,10 +444,11 @@ async def setup_plugins(app: FastAPI):
444444
)
445445
builtin_plugin = ObfuscateTags
446446
name = f"{builtin_plugin.__module__}"
447+
short_name = name.split(".")[-1]
447448
app.state.plugins.append(builtin_plugin)
448-
app.state.plugin_contexts[name] = {"config": config.get_plugin_config(name)}
449+
plugin_config = config.get_plugin_config(short_name)
450+
app.state.plugin_contexts[name] = {"config": plugin_config}
449451
if hasattr(builtin_plugin, "setup"):
450-
plugin_config = config.get_plugin_config(name)
451452
setup_args = {
452453
"config": plugin_config,
453454
"context": app.state.plugin_contexts[name],

gsrest/builtin/plugins/obfuscate_tags/obfuscate_tags.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ def before_response(cls, context: dict, request: Request, result: Any) -> None:
104104
for x in get_request_header(request, GROUPS_HEADER_NAME, "").split(",")
105105
]
106106

107-
obfuscate_tagpack_uri_rule = context.get("config", {}).get(
107+
obfuscate_tagpack_uri_rule = (context.get("config") or {}).get(
108108
"obfuscate_tagpack_uri_rule", None
109109
)
110110

gsrest/dependencies.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,4 +256,11 @@ def get_username(request) -> Optional[str]:
256256

257257

258258
def should_obfuscate_private_tags(request) -> bool:
259+
# Check header modifications from plugin middleware first
260+
header_mods = getattr(request, "state", None)
261+
if header_mods is not None:
262+
header_mods = getattr(header_mods, "header_modifications", {})
263+
if header_mods.get(GROUPS_HEADER_NAME) == OBFUSCATION_MARKER_GROUP:
264+
return True
265+
# Fall back to checking actual headers
259266
return request.headers.get(GROUPS_HEADER_NAME, "") == OBFUSCATION_MARKER_GROUP

gsrest/routes/base.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ def __getitem__(self, key):
6262
def headers(self):
6363
return self._fastapi_request.headers
6464

65+
@property
66+
def state(self):
67+
return self._fastapi_request.state
68+
6569

6670
def apply_plugin_hooks(request: Request, result):
6771
"""Apply plugin response hooks to a result.

tests/test_fastapi_migration.py

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
# Start old server on port 9001
99
GS_REST_DEV_PORT=9001 make serve-old
1010
11-
# Start new FastAPI server on port 9002
12-
uv run uvicorn gsrest.app:create_app --factory --port 9002
11+
# Start new FastAPI server on port 9000
12+
uv run uvicorn gsrest.app:create_app --factory --port 9000
1313
1414
# Run comparison tests
1515
uv run pytest tests/test_fastapi_migration.py -v -s
@@ -33,12 +33,13 @@
3333

3434
# Server endpoints - can be overridden via environment variables
3535
OLD_SERVER = os.environ.get("OLD_SERVER", "http://localhost:9001")
36-
NEW_SERVER = os.environ.get("NEW_SERVER", "http://localhost:9002")
36+
NEW_SERVER = os.environ.get("NEW_SERVER", "http://localhost:9000")
3737

3838
HEADERS = {"Content-Type": "application/json", "Accept": "application/json"}
3939

4040
# Test data constants
4141
BTC_ADDRESS = "1Archive1n2C579dMsAu3iC6tWzuQJz8dN"
42+
BTC_ADDRESS_PRIVATE_TAGS = "3D4gm7eGSXiEkWS5V3hN9kDVo2eDGBK4eA" # Address with potentially private tags
4243
ETH_ADDRESS = "0xdac17f958d2ee523a2206206994597c13d831ec7"
4344
BTC_ENTITY = 109578
4445
BTC_TX = "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"
@@ -681,6 +682,55 @@ def test_supported_tokens(self):
681682
self.assert_endpoint_equal("eth/supported_tokens")
682683

683684

685+
class TestAddressObfuscation(MigrationTestBase):
686+
"""Test address/entity endpoints to verify tag obfuscation behavior is consistent.
687+
688+
These tests verify that tag/actor obfuscation works identically between
689+
the old aiohttp and new FastAPI implementations for addresses with:
690+
- Public tags (1Archive1n2C579dMsAu3iC6tWzuQJz8dN - Internet Archive)
691+
- Potentially private tags (3D4gm7eGSXiEkWS5V3hN9kDVo2eDGBK4eA)
692+
693+
Tests use endpoints where obfuscation is actually applied:
694+
- /addresses/{addr}/entity - obfuscates best_address_tag and actors
695+
- /addresses/{addr}/tag_summary - obfuscates via tag_transformer in service
696+
- /entities/{entity}/tags - obfuscates private tag labels
697+
"""
698+
699+
@pytest.mark.migration
700+
@pytest.mark.parametrize("address", [BTC_ADDRESS, BTC_ADDRESS_PRIVATE_TAGS])
701+
def test_address_entity_obfuscation(self, address):
702+
"""Test address entity endpoint (obfuscation applies to best_address_tag and actors)."""
703+
self.assert_endpoint_equal(f"btc/addresses/{address}/entity")
704+
705+
@pytest.mark.migration
706+
@pytest.mark.parametrize("address", [BTC_ADDRESS, BTC_ADDRESS_PRIVATE_TAGS])
707+
def test_tag_summary_obfuscation(self, address):
708+
"""Test tag_summary endpoint with obfuscation.
709+
710+
This endpoint uses a tag_transformer in the service layer which checks
711+
should_obfuscate_private_tags(). Without private group headers,
712+
private tags should be obfuscated.
713+
"""
714+
self.assert_endpoint_equal(
715+
f"btc/addresses/{address}/tag_summary?include_best_cluster_tag=true"
716+
)
717+
718+
@pytest.mark.migration
719+
@pytest.mark.parametrize("address", [BTC_ADDRESS, BTC_ADDRESS_PRIVATE_TAGS])
720+
def test_entity_tags_obfuscation(self, address):
721+
"""Test entity tags endpoint (obfuscation applies to private tags).
722+
723+
Looks up the entity ID from the address first, then compares entity tags.
724+
"""
725+
# Get entity ID from address
726+
data, status, _ = get_response(NEW_SERVER, f"btc/addresses/{address}/entity")
727+
assert status == 200, f"Failed to get entity for {address}"
728+
entity_id = data["entity"]
729+
730+
# Compare entity tags between old and new
731+
self.assert_endpoint_equal(f"btc/entities/{entity_id}/tags")
732+
733+
684734
class TestSearchParameters(MigrationTestBase):
685735
"""Test search endpoint with various parameter configurations."""
686736

tests/test_regression.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ def compare_instances(call) -> Dict[str, Any]:
126126
logger.error(f"Error during testing: {e}")
127127
raise
128128

129+
129130
@pytest.mark.regression
130131
def test_conversions():
131132
"""Run the regression test and return the comparison result."""

0 commit comments

Comments
 (0)