Commit 5e2edae
committed
Resolve dot segments in linear time when canonicalizing a URL
## Motivation and Context
`Discovery.canonicalize_url` resolved dot segments with RFC 3986 Section 5.2.4 applied literally:
every `.` or `..` rewrote the remaining input buffer, which copies it each time, so the cost grew with the square
of the path's length. The path is the server's to choose, through a Protected Resource Metadata `resource`
or an endpoint URL that reaches the canonicalization: resolving a 2 MB path made of `a/../` took over 30 seconds,
on every flow that received it.
The segments are now visited once with a stack, which is the same algorithm expressed over segments instead of
over the buffer. The output is unchanged, including the RFC's handling of a trailing `/.`
or `/..` (the slash stays) and of a relative path (which `URI#path` never yields), as checked against
the previous implementation on 100,000 random paths.
## How Has This Been Tested?
New tests in `test/mcp/client/oauth/discovery_test.rb` canonicalize a URL with 300,000 dot segments within
a bound the previous implementation exceeded many times over, and pin the trailing-slash and empty-segment cases.
## Breaking Changes
None.1 parent c9641fb commit 5e2edae
2 files changed
Lines changed: 56 additions & 34 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
579 | 579 | | |
580 | 580 | | |
581 | 581 | | |
582 | | - | |
583 | | - | |
584 | | - | |
585 | | - | |
| 582 | + | |
| 583 | + | |
| 584 | + | |
| 585 | + | |
| 586 | + | |
| 587 | + | |
| 588 | + | |
586 | 589 | | |
587 | 590 | | |
588 | 591 | | |
589 | 592 | | |
590 | | - | |
591 | | - | |
592 | | - | |
593 | | - | |
594 | | - | |
595 | | - | |
596 | | - | |
597 | | - | |
598 | | - | |
599 | | - | |
600 | | - | |
601 | | - | |
602 | | - | |
603 | | - | |
604 | | - | |
605 | | - | |
606 | | - | |
607 | | - | |
608 | | - | |
| 593 | + | |
| 594 | + | |
| 595 | + | |
| 596 | + | |
| 597 | + | |
| 598 | + | |
| 599 | + | |
| 600 | + | |
| 601 | + | |
| 602 | + | |
| 603 | + | |
| 604 | + | |
| 605 | + | |
| 606 | + | |
| 607 | + | |
| 608 | + | |
| 609 | + | |
| 610 | + | |
| 611 | + | |
| 612 | + | |
| 613 | + | |
| 614 | + | |
609 | 615 | | |
610 | | - | |
611 | | - | |
612 | | - | |
| 616 | + | |
| 617 | + | |
613 | 618 | | |
| 619 | + | |
614 | 620 | | |
615 | | - | |
616 | | - | |
617 | | - | |
618 | | - | |
619 | | - | |
620 | | - | |
621 | | - | |
622 | | - | |
| 621 | + | |
623 | 622 | | |
624 | 623 | | |
625 | 624 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
291 | 291 | | |
292 | 292 | | |
293 | 293 | | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
294 | 317 | | |
295 | 318 | | |
296 | 319 | | |
| |||
0 commit comments