Skip to content

Commit df17132

Browse files
feat: improved the uri mask used in the http client aspect and in the middleware tracker (#30)
1 parent 33edd8f commit df17132

File tree

4 files changed

+199
-22
lines changed

4 files changed

+199
-22
lines changed

src/Aspect/HttpClientAspect.php

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,16 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint)
7272
$method = strtoupper($arguments['keys']['method'] ?? '');
7373
$uri = $arguments['keys']['uri'] ?? '';
7474
$host = $base_uri === null ? (parse_url($uri, PHP_URL_HOST) ?? '') : $base_uri->getHost();
75+
$uriMask = $this->getUriMask($instance);
76+
$uri = $this->shouldIgnoreUri($instance)
77+
? '<IGNORED>'
78+
: SupportUri::sanitize(parse_url($uri, PHP_URL_PATH) ?? '/', $uriMask);
7579
$span = $this->startSpan(
7680
sprintf(
7781
'%s %s/%s',
7882
$method,
79-
rtrim((string) ($base_uri ?? ''), '/'),
80-
ltrim(parse_url(SupportUri::sanitize($uri), PHP_URL_PATH) ?? '', '/')
83+
$host,
84+
$uri
8185
)
8286
);
8387

@@ -117,6 +121,22 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint)
117121
return $result;
118122
}
119123

124+
private function shouldIgnoreUri(Client $instance): bool
125+
{
126+
return $instance->getConfig('ignore_uri') === true;
127+
}
128+
129+
public function getUriMask(Client $instance): array
130+
{
131+
$uriMask = $instance->getConfig('uri_mask');
132+
133+
if (is_array($uriMask) === false) {
134+
return [];
135+
}
136+
137+
return $uriMask;
138+
}
139+
120140
protected function appendCustomSpan(Span $span, array $options): void
121141
{
122142
// just for override

src/Middleware/TraceMiddleware.php

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ protected function appendCustomResponseSpan(Span $span, ServerRequestInterface $
124124

125125
protected function buildSpan(ServerRequestInterface $request): Span
126126
{
127-
$path = $this->getPath($request->getUri());
127+
$path = $this->getPath($request);
128128
$spanName = sprintf('%s %s', $request->getMethod(), $path);
129129

130130
$span = $this->startSpan($spanName, [], SPAN_KIND_RPC_SERVER);
@@ -156,8 +156,20 @@ protected function buildSpan(ServerRequestInterface $request): Span
156156
return $span;
157157
}
158158

159-
protected function getPath(UriInterface $uri): string
159+
protected function getPath(ServerRequestInterface $request): string
160160
{
161-
return Uri::sanitize($uri->getPath());
161+
$dispatched = $request->getAttribute(Dispatched::class);
162+
if (! $dispatched) {
163+
return Uri::sanitize($request->getUri()->getPath(), $this->getUriMask());
164+
}
165+
if (! $dispatched->handler) {
166+
return 'not_found';
167+
}
168+
return $dispatched->handler->route;
169+
}
170+
171+
protected function getUriMask(): array
172+
{
173+
return is_array($this->config['uri_mask'])? $this->config['uri_mask'] : [];
162174
}
163175
}

src/Support/Uri.php

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,36 @@
1313

1414
final class Uri
1515
{
16-
public static function sanitize(string $uri): string
16+
public static function sanitize(string $uri, array $uriMask = []): string
1717
{
1818
return preg_replace(
19-
[
20-
'/\/(?<=\/)([A-F0-9]{8}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{12})(?=\/)?/i',
21-
'/\/(?<=\/)((?=.{7,8}$)|(?=.{7,8}\/))([A-Z]{3}-?\d[0-9A-Z]\d{2})/i',
22-
'/\/(?<=\/)[0-9A-F]{24,}(?=\/)?/i',
23-
'/\/(?<=\/)\d+(?=\/)?/',
24-
],
25-
[
26-
'/<UUID>',
27-
'/<LICENSE-PLATE>',
28-
'/<OID>',
29-
'/<NUMBER>',
30-
],
31-
$uri
19+
array_merge(
20+
array_keys($uriMask),
21+
[
22+
'/\/(?<=\/)[ED]\d{8}\d{12}[0-9a-zA-Z]{11}(?=\/)?/',
23+
'/\/(?<=\/)[a-f0-9]{40}(?=\/)?/i',
24+
'/\/(?<=\/)([A-F0-9]{8}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{12})(?=\/)?/i',
25+
'/\/(?<=\/)([A-Z]{3}-?\d[0-9A-Z]\d{2})(?=\/)?/i',
26+
'/\/(?<=\/)[0-9A-F]{16,24}(?=\/)?/i',
27+
'/\/(?<=\/)\d+(?=\/)?/',
28+
'/\/(?<=\/)R[RN]\d{16}[A-Za-z0-9]{11}/',
29+
'/\/([A-Z]{3,}(?:-[A-Z]{3,})*)-([A-Z0-9]{3}-\d+(?:_\d{3})?|[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}|[A-Za-z0-9]{8,})(?=\/|$)/i',
30+
],
31+
),
32+
array_merge(
33+
array_values($uriMask),
34+
[
35+
'/<E2E-ID>',
36+
'/<SHA1>',
37+
'/<UUID>',
38+
'/<LICENSE-PLATE>',
39+
'/<OID>',
40+
'/<NUMBER>',
41+
'/<EXTERNAL-ID>',
42+
'/<PREFIXED-ID>',
43+
],
44+
),
45+
'/' . ltrim($uri, '/'),
3246
);
3347
}
3448
}

tests/UriTest.php

Lines changed: 134 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public function testClearUriUuids(): void
6969
public function testClearUriOids(): void
7070
{
7171
$oid = '650229807612bba4984d1fc7';
72-
$oidLonger = 'ddb21302b3c66b5111bb99a907f783e2a29947f0';
72+
$oidShort = '65022612bba84d1f';
7373

7474
self::assertSame('/v1/test', Uri::sanitize('/v1/test'));
7575
self::assertSame('/v2/test/<OID>', Uri::sanitize("/v2/test/{$oid}"));
@@ -79,7 +79,138 @@ public function testClearUriOids(): void
7979
self::assertSame('/v6/test/<OID>/<OID>/', Uri::sanitize("/v6/test/{$oid}/{$oid}/"));
8080
self::assertSame('/v7/test/<OID>/<OID>/<OID>', Uri::sanitize("/v7/test/{$oid}/{$oid}/{$oid}"));
8181
self::assertSame('/v8/test/<OID>/<OID>/<OID>/', Uri::sanitize("/v8/test/{$oid}/{$oid}/{$oid}/"));
82-
self::assertSame('/v2/token/<OID>/foo/<OID>', Uri::sanitize("/v2/token/{$oidLonger}/foo/{$oid}"));
83-
self::assertSame('/v3/token/<OID>/foo/<OID>/bar', Uri::sanitize("/v3/token/$oidLonger/foo/{$oid}/bar"));
82+
self::assertSame('/v9/test/<OID>/bar/<NUMBER>', Uri::sanitize("/v9/test/{$oidShort}/bar/12345"));
83+
}
84+
85+
public function testAddsInitialSlash(): void
86+
{
87+
self::assertSame('/v1/', Uri::sanitize('/v1/'));
88+
self::assertSame('/v1', Uri::sanitize('v1'));
89+
self::assertSame('/v1/', Uri::sanitize('v1/'));
90+
self::assertSame('/v1/test/', Uri::sanitize('/v1/test/'));
91+
self::assertSame('/v1/test', Uri::sanitize('v1/test'));
92+
self::assertSame('/v1/test/', Uri::sanitize('v1/test/'));
93+
}
94+
95+
public function testAndroidId(): void
96+
{
97+
$this->markTestSkipped();
98+
99+
self::assertSame('/device/<ANDROID-ID>/user/<NUMBER>', Uri::sanitize('/devices/a436d9ffefef80e8/user/999'));
100+
self::assertSame('/device/<ANDROID-ID>/user/<NUMBER>', Uri::sanitize('/devices/7b5d68f217d90ff5/user/999'));
101+
self::assertSame('/device/<ANDROID-ID>/user/<NUMBER>', Uri::sanitize('/devices/dc900fb903cc308c/user/999'));
102+
self::assertSame('/device/<ANDROID-ID>/user/<NUMBER>', Uri::sanitize('/devices/86d144c9078c8176/user/999'));
103+
self::assertSame('/device/<ANDROID-ID>/user/<NUMBER>', Uri::sanitize('/devices/86d144c9078c8176/user/8045169'));
104+
}
105+
106+
public function testSanitizeHashsStrings(): void
107+
{
108+
self::assertSame('/v1/test', Uri::sanitize('/v1/test'));
109+
self::assertSame('/v2/test/<SHA1>', Uri::sanitize('/v2/test/141da78905dcaa7ed8d4da7c3f49a2415ebdc110'));
110+
self::assertSame('/v2/test/<SHA1>', Uri::sanitize('/v2/test/7110EDA4D09E062AA5E4A390B0A572AC0D2C0220'));
111+
self::assertSame('/v3/test/<SHA1>/bar', Uri::sanitize('/v3/test/81FE8BFE87576C3ECB22426F8E57847382917ACF/bar'));
112+
self::assertSame('/v3/test/<SHA1>/bar', Uri::sanitize('/v3/test/7110EDA4D09E062AA5E4A390B0A572AC0D2C0220/bar'));
113+
self::assertSame('/v4/test/<SHA1>/bar/<SHA1>/', Uri::sanitize('/v4/test/141da78905dcaa7ed8d4da7c3f49a2415ebdc110/bar/141da78905dcaa7ed8d4da7c3f49a2415ebdc110/'));
114+
self::assertSame('/v4/test/<SHA1>/bar/<SHA1>/', Uri::sanitize('/v4/test/7110EDA4D09E062AA5E4A390B0A572AC0D2C0220/bar/7110EDA4D09E062AA5E4A390B0A572AC0D2C0220/'));
115+
self::assertSame('/v5/test/<SHA1>/<SHA1>', Uri::sanitize('/v5/test/141da78905dcaa7ed8d4da7c3f49a2415ebdc110/141da78905dcaa7ed8d4da7c3f49a2415ebdc110'));
116+
self::assertSame('/v5/test/<SHA1>/<SHA1>', Uri::sanitize('/v5/test/7110EDA4D09E062AA5E4A390B0A572AC0D2C0220/7110EDA4D09E062AA5E4A390B0A572AC0D2C0220'));
117+
self::assertSame('/v6/test/<SHA1>/<SHA1>/', Uri::sanitize('/v6/test/141da78905dcaa7ed8d4da7c3f49a2415ebdc110/141da78905dcaa7ed8d4da7c3f49a2415ebdc110/'));
118+
self::assertSame('/v6/test/<SHA1>/<SHA1>/', Uri::sanitize('/v6/test/7110EDA4D09E062AA5E4A390B0A572AC0D2C0220/7110EDA4D09E062AA5E4A390B0A572AC0D2C0220/'));
119+
self::assertSame('/v7/test/<SHA1>/<SHA1>/<SHA1>', Uri::sanitize('/v7/test/141da78905dcaa7ed8d4da7c3f49a2415ebdc110/141da78905dcaa7ed8d4da7c3f49a2415ebdc110/141da78905dcaa7ed8d4da7c3f49a2415ebdc110'));
120+
self::assertSame('/v7/test/<SHA1>/<SHA1>/<SHA1>', Uri::sanitize('/v7/test/7110EDA4D09E062AA5E4A390B0A572AC0D2C0220/7110EDA4D09E062AA5E4A390B0A572AC0D2C0220/7110EDA4D09E062AA5E4A390B0A572AC0D2C0220'));
121+
self::assertSame('/v8/test/<SHA1>/<SHA1>/<SHA1>/', Uri::sanitize('/v8/test/141da78905dcaa7ed8d4da7c3f49a2415ebdc110/141da78905dcaa7ed8d4da7c3f49a2415ebdc110/141da78905dcaa7ed8d4da7c3f49a2415ebdc110/'));
122+
self::assertSame('/v8/test/<SHA1>/<SHA1>/<SHA1>/', Uri::sanitize('/v8/test/7110EDA4D09E062AA5E4A390B0A572AC0D2C0220/7110EDA4D09E062AA5E4A390B0A572AC0D2C0220/7110EDA4D09E062AA5E4A390B0A572AC0D2C0220/'));
123+
}
124+
125+
public function testSanitizeEndToEndId(): void
126+
{
127+
$e2eid = 'E99999999202401010000abcDEF12345';
128+
129+
self::assertSame('/v1/test', Uri::sanitize('/v1/test'));
130+
self::assertSame('/v2/test/<E2E-ID>', Uri::sanitize("/v2/test/{$e2eid}"));
131+
self::assertSame('/v3/test/<E2E-ID>/bar', Uri::sanitize("/v3/test/{$e2eid}/bar"));
132+
self::assertSame('/v4/test/<E2E-ID>/bar/<E2E-ID>/', Uri::sanitize("/v4/test/{$e2eid}/bar/{$e2eid}/"));
133+
self::assertSame('/v5/test/<E2E-ID>/<E2E-ID>', Uri::sanitize("/v5/test/{$e2eid}/{$e2eid}"));
134+
self::assertSame('/v6/test/<E2E-ID>/<E2E-ID>/', Uri::sanitize("/v6/test/{$e2eid}/{$e2eid}/"));
135+
self::assertSame('/v7/test/<E2E-ID>/<E2E-ID>/<E2E-ID>', Uri::sanitize("/v7/test/{$e2eid}/{$e2eid}/{$e2eid}"));
136+
self::assertSame('/v8/test/<E2E-ID>/<E2E-ID>/<E2E-ID>/', Uri::sanitize("/v8/test/{$e2eid}/{$e2eid}/{$e2eid}/"));
137+
}
138+
139+
public function testWithMaskParams(): void
140+
{
141+
$uriMask = [
142+
'/\/[a-f0-9]{64}/i' => '/<SHA256-ID>',
143+
];
144+
145+
self::assertSame('/v1/test', Uri::sanitize('/v1/test', $uriMask));
146+
self::assertSame('/v2/test/<SHA256-ID>', Uri::sanitize('/v2/test/54cf575c04fdef4667094b6fc4fab8014dd3fa53576b644ec399452c43b5e7f7', $uriMask));
147+
self::assertSame('/v3/test/<SHA256-ID>/bar', Uri::sanitize('/v3/test/54cf575c04fdef4667094b6fc4fab8014dd3fa53576b644ec399452c43b5e7f7/bar', $uriMask));
148+
self::assertSame('/v4/test/<SHA256-ID>/bar/<SHA256-ID>/', Uri::sanitize('/v4/test/54cf575c04fdef4667094b6fc4fab8014dd3fa53576b644ec399452c43b5e7f7/bar/54cf575c04fdef4667094b6fc4fab8014dd3fa53576b644ec399452c43b5e7f7/', $uriMask));
149+
self::assertSame('/v5/test/<SHA256-ID>/<SHA256-ID>', Uri::sanitize('/v5/test/54cf575c04fdef4667094b6fc4fab8014dd3fa53576b644ec399452c43b5e7f7/54cf575c04fdef4667094b6fc4fab8014dd3fa53576b644ec399452c43b5e7f7', $uriMask));
150+
self::assertSame('/v6/test/<SHA256-ID>/<SHA256-ID>/', Uri::sanitize('/v6/test/54cf575c04fdef4667094b6fc4fab8014dd3fa53576b644ec399452c43b5e7f7/54cf575c04fdef4667094b6fc4fab8014dd3fa53576b644ec399452c43b5e7f7/', $uriMask));
151+
self::assertSame('/v7/test/<SHA256-ID>/<SHA256-ID>/<SHA256-ID>', Uri::sanitize('/v7/test/54cf575c04fdef4667094b6fc4fab8014dd3fa53576b644ec399452c43b5e7f7/54cf575c04fdef4667094b6fc4fab8014dd3fa53576b644ec399452c43b5e7f7/54cf575c04fdef4667094b6fc4fab8014dd3fa53576b644ec399452c43b5e7f7', $uriMask));
152+
self::assertSame('/v8/test/<SHA256-ID>/<SHA256-ID>/<SHA256-ID>/', Uri::sanitize('/v8/test/54cf575c04fdef4667094b6fc4fab8014dd3fa53576b644ec399452c43b5e7f7/54cf575c04fdef4667094b6fc4fab8014dd3fa53576b644ec399452c43b5e7f7/54cf575c04fdef4667094b6fc4fab8014dd3fa53576b644ec399452c43b5e7f7/', $uriMask));
153+
}
154+
155+
public function testClearUriExternalIds(): void
156+
{
157+
self::assertSame('/v1/test', Uri::sanitize('/v1/test'));
158+
self::assertSame('/v1/test/<EXTERNAL-ID>', Uri::sanitize('/v1/test/RR2101818220123720H9KJTERfw1a'));
159+
self::assertSame('/v3/test/<EXTERNAL-ID>/bar', Uri::sanitize('/v3/test/RN2401818220250720G4KJTQyU6Ds/bar'));
160+
self::assertSame('/v4/test/<EXTERNAL-ID>/bar/<EXTERNAL-ID>/', Uri::sanitize('/v4/test/RR2101818220123720H9KJTERfw1a/bar/RN2401818220250720G4KJTQyU6Ds/'));
161+
self::assertSame('/v5/test/<EXTERNAL-ID>/<EXTERNAL-ID>', Uri::sanitize('/v5/test/RR2101818220123720H9KJTERfw1a/RN2401818220250720G4KJTQyU6Ds'));
162+
self::assertSame('/v7/test/<EXTERNAL-ID>/<EXTERNAL-ID>/<EXTERNAL-ID>/', Uri::sanitize('/v7/test/RR2101818220123720H9KJTERfw1a/RN2001818220123720H9KJTERBd52/RR2123818220123730H9KJTERBd52/'));
163+
self::assertSame('/v9/test/<EXTERNAL-ID>/bar/<NUMBER>', Uri::sanitize('/v9/test/RR2101818220123720H9KJTERfw1a/bar/12345'));
164+
}
165+
166+
public function testClearUriPrefixedId(): void
167+
{
168+
// Casos de teste específicos solicitados
169+
$ecosystemId1 = 'ECOSYSTEM-PPF-0100206721_003';
170+
$ecosystemId2 = 'ECOSYSTEM-EPF-0100308183_001';
171+
$ecosystemId3 = 'ECOSYSTEM-ESF-105454545';
172+
$billUuid = 'BILL-1811cd92-ed15-4b8a-a571-6cfa44002703';
173+
174+
// Testes básicos
175+
self::assertSame('/v1/test', Uri::sanitize('/v1/test'));
176+
177+
// Testes com ECOSYSTEM-PPF-0100206721_003
178+
self::assertSame('/v2/test/<PREFIXED-ID>', Uri::sanitize("/v2/test/{$ecosystemId1}"));
179+
self::assertSame('/v3/test/<PREFIXED-ID>/bar', Uri::sanitize("/v3/test/{$ecosystemId1}/bar"));
180+
self::assertSame('/v4/test/<PREFIXED-ID>/bar/<PREFIXED-ID>/', Uri::sanitize("/v4/test/{$ecosystemId1}/bar/{$ecosystemId1}/"));
181+
182+
// Testes com ECOSYSTEM-EPF-0100308183_001
183+
self::assertSame('/v5/test/<PREFIXED-ID>', Uri::sanitize("/v5/test/{$ecosystemId2}"));
184+
self::assertSame('/v6/test/<PREFIXED-ID>/details', Uri::sanitize("/v6/test/{$ecosystemId2}/details"));
185+
self::assertSame('/v7/test/<PREFIXED-ID>/<PREFIXED-ID>', Uri::sanitize("/v7/test/{$ecosystemId2}/{$ecosystemId1}"));
186+
187+
// Testes com ECOSYSTEM-ESF-105454545
188+
self::assertSame('/v8/test/<PREFIXED-ID>', Uri::sanitize("/v8/test/{$ecosystemId3}"));
189+
self::assertSame('/v9/test/<PREFIXED-ID>/config', Uri::sanitize("/v9/test/{$ecosystemId3}/config"));
190+
191+
// Testes com BILL-1811cd92-ed15-4b8a-a571-6cfa44002703
192+
self::assertSame('/v10/test/<PREFIXED-ID>', Uri::sanitize("/v10/test/{$billUuid}"));
193+
self::assertSame('/v11/test/<PREFIXED-ID>/profile', Uri::sanitize("/v11/test/{$billUuid}/profile"));
194+
self::assertSame('/v12/test/<PREFIXED-ID>/bar/<PREFIXED-ID>/', Uri::sanitize("/v12/test/{$billUuid}/bar/{$billUuid}/"));
195+
196+
// Testes mistos entre os IDs
197+
self::assertSame('/v13/test/<PREFIXED-ID>/<PREFIXED-ID>', Uri::sanitize("/v13/test/{$billUuid}/{$ecosystemId3}"));
198+
self::assertSame('/v14/test/<PREFIXED-ID>/<PREFIXED-ID>/<PREFIXED-ID>', Uri::sanitize("/v14/test/{$ecosystemId1}/{$ecosystemId2}/{$billUuid}"));
199+
self::assertSame('/v15/test/<PREFIXED-ID>/<PREFIXED-ID>/<PREFIXED-ID>/', Uri::sanitize("/v15/test/{$ecosystemId3}/{$billUuid}/{$ecosystemId1}/"));
200+
201+
// Casos edge: diferentes contextos de API
202+
self::assertSame('/users/<PREFIXED-ID>/profile', Uri::sanitize("/users/{$billUuid}/profile"));
203+
self::assertSame('/api/v1/bills/<PREFIXED-ID>/details', Uri::sanitize("/api/v1/bills/{$billUuid}/details"));
204+
self::assertSame('/ecosystems/<PREFIXED-ID>/platform/<PREFIXED-ID>', Uri::sanitize("/ecosystems/{$ecosystemId1}/platform/{$ecosystemId2}"));
205+
self::assertSame('/companies/<PREFIXED-ID>/admin/<PREFIXED-ID>/settings', Uri::sanitize("/companies/{$billUuid}/admin/{$ecosystemId3}/settings"));
206+
207+
// Casos críticos: evitar falsos positivos
208+
self::assertSame('/pic-pay/entry/id/<PREFIXED-ID>', Uri::sanitize("/pic-pay/entry/id/{$ecosystemId3}"));
209+
self::assertSame('/api-gateway/service/<PREFIXED-ID>', Uri::sanitize("/api-gateway/service/{$ecosystemId2}"));
210+
self::assertSame('/health-check/status/<PREFIXED-ID>', Uri::sanitize("/health-check/status/{$billUuid}"));
211+
212+
// Teste sem barra final
213+
self::assertSame('/test/<PREFIXED-ID>', Uri::sanitize("/test/{$billUuid}"));
214+
self::assertSame('/ecosystem/<PREFIXED-ID>', Uri::sanitize("/ecosystem/{$ecosystemId1}"));
84215
}
85216
}

0 commit comments

Comments
 (0)