Skip to content

RFC: Update route syntax - #10

Merged
tigerwill90 merged 19 commits into
masterfrom
route-format-declaration
Apr 1, 2023
Merged

tigerwill90 merged 19 commits into
masterfrom
route-format-declaration

Conversation

@tigerwill90

@tigerwill90 tigerwill90 commented Mar 28, 2023 •

Copy link
Copy Markdown
Collaborator

Introduction

This RFC proposes to update the current route declaration format for named and catch-all parameters by using {} and *{} or {*} as delimiters instead of : and *. This change aims to improve compatibility with common URL patterns and provide greater flexibility for mixing static and named route segments.

Motivation

The current route declaration format using : for named parameters and * for catch-all parameters has some limitations in terms of readability, especially when working with certain API patterns. For instance, /users/uid:1234/profile is relatively common pattern in APIs, and the proposed change would make it easier to define such routes by providing more intuitive delimiters (e.g. /users/uid:{id}/profile).

Additionally, the current format limits the flexibility to mix static and named route segments in the same path segment. For example, consider the route /date/{year}-{month}-{day}. With the current format, this would have to be defined as /date/:ymd and require additional parsing of the ymd parameter to extract the year, month, and day. The proposed format with {} delimiters allows for more intuitive and straightforward route definitions. In the new format, each named parameter is defined explicitly and can be accessed directly without the need for additional parsing.

The new syntax also paves the way for more advanced routing features, such as incorporating regular expressions directly into route definitions (e.g /users/{id:[0-9]+}).

Design

The proposed update involves changing the route declaration format for named and catch-all parameters as follows:

  1. Replace : with {} as the delimiter for named parameters.
  2. Replace * with *{} or {*} as the delimiter for catch-all parameters.

Examples

Current declaration:

Pattern /users/:id
Pattern /*filepath

Updated declaration:

Pattern /users/{id}
Pattern /*{filepath} or /{*filepath}

Direct benefits

This new design would also provide more flexible route declaration

  1. Date and time: /datetime/{year}-{month}-{day}T{hour}:{minute}:{second}
    Example: /datetime/2023-03-26T18:30:15
  2. Geocoordinates: /geo/{latitude},{longitude}
    Example: /geo/37.7749,-122.4194
  3. Product size and color: /products/{product_id}-size{size}-color{color}
    Example: /products/1234-sizeM-colorRed
  4. User ID with domain: /users/{user_id}@{domain}/profile
    Example: /users/1234@example.com/profile

Drawbacks

  • Potential increase in code complexity
  • Potential impact on performance

Conclusion

The proposed new syntax aims to enhance readability and flexibility when declaring routes. At the same time, the intention is to improve the routing experience without compromising efficiency and speed. As such, the acceptance of this proposal is contingent upon ensuring that the impact on performance remains minimal to negligible.

@tigerwill90 tigerwill90 changed the title Init RFC RFC: Update route declaration format for Named and Catch-All parameters Mar 28, 2023
@tigerwill90
tigerwill90 requested review from 4nth0 and rewiko March 28, 2023 16:30
@tigerwill90 tigerwill90 self-assigned this Mar 28, 2023
@tigerwill90 tigerwill90 changed the title RFC: Update route declaration format for Named and Catch-All parameters RFC: Update route syntax Mar 28, 2023
@tigerwill90

tigerwill90 commented Mar 28, 2023 •

Copy link
Copy Markdown
Collaborator Author

After conducting a series of implementation experiments based on the RFC proposal to update the route declaration format, there is a significant performance impact when mixing static and named parameters within a single route segment, specifically when the static part follows the named parameter and the node in question has 1..n children.

For example, consider the following route declarations:

Pattern /users/{id}
Pattern /users/{id}@email
Pattern /users/{id}-phone

In this context, when processing a request such as /users/12345-phone, the router must search for the next static match (the - character) examining each character of the path [1, 2, 3, 4, 5, -] until it match one of the child node.

for i := 0; i < len(remainingCharsInPath); i++ {
    idx := linearSearch(current.childKeys, remainingCharsInPath[i])
    if idx >= 0 {
	break
   }
   charsMatched++
}

The impact becomes more significant as the segment to match increases in size and the number of child node grow.

To mitigate this performance impact, the router must enforces certain restrictions on the route format, such as allowing only one parameter per path segment and requiring that a parameter be directly followed by a slash or the end of the route. These restrictions simplify the matching process when attempting to identify the end of a parameter within a path segment. By knowing that a parameter is always followed by a slash or the end of the route, the router can quickly determine the boundary of the parameter and reduce the amount of searching required, leading to better overall performance.

@tigerwill90
tigerwill90 force-pushed the route-format-declaration branch from f4753de to e83a755 Compare March 29, 2023 10:04
@tigerwill90

tigerwill90 commented Mar 31, 2023 •

Copy link
Copy Markdown
Collaborator Author
goos: linux
goarch: amd64
pkg: github.com/tigerwill90/fox
cpu: Intel(R) Core(TM) i9-9900K CPU @ 3.60GHz
                    │   old.txt    │              new.txt               │
                    │    sec/op    │   sec/op     vs base               │
StaticAll-16          7.898µ ±  3%   7.809µ ± 3%       ~ (p=0.190 n=10)
Lookup-16             6.237µ ±  1%   6.260µ ± 2%       ~ (p=0.247 n=10)
GithubParamsAll-16    85.95n ±  6%   78.69n ± 4%  -8.45% (p=0.000 n=10)
StaticParallel-16     6.540n ±  4%   6.399n ± 3%  -2.15% (p=0.043 n=10)
CatchAll-16           32.86n ±  8%   30.74n ± 2%  -6.47% (p=0.000 n=10)
CatchAllParallel-16   5.598n ± 16%   5.264n ± 9%       ~ (p=0.077 n=10)
geomean               131.2n         125.9n       -4.02%

Benchmark shows a 4.02% overall performance improvement. No significant change observed for static route and small improvement on wildcard route.

@fox-toolkit fox-toolkit deleted a comment from codecov Bot Mar 31, 2023
@fox-toolkit fox-toolkit deleted a comment from codecov Bot Mar 31, 2023
@tigerwill90
tigerwill90 requested a review from pawndev March 31, 2023 18:26
@tigerwill90
tigerwill90 marked this pull request as ready for review March 31, 2023 18:28
@fox-toolkit fox-toolkit deleted a comment from codecov Bot Mar 31, 2023
@codecov

codecov Bot commented Mar 31, 2023 •

Copy link
Copy Markdown

Codecov Report

Merging #10 (d89b3f8) into master (142f137) will increase coverage by 0.34%.
The diff coverage is 100.00%.

@@            Coverage Diff             @@
##           master      #10      +/-   ##
==========================================
+ Coverage   87.55%   87.89%   +0.34%     
==========================================
  Files           8        8              
  Lines        1221     1231      +10     
==========================================
+ Hits         1069     1082      +13     
+ Misses        128      123       -5     
- Partials       24       26       +2     
Flag Coverage Δ
coverage.txt 87.89% <100.00%> (+0.34%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
node.go 73.94% <100.00%> (ø)
router.go 88.47% <100.00%> (+0.92%) ⬆️
tree.go 89.27% <100.00%> (+0.34%) ⬆️

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

@tigerwill90
tigerwill90 merged commit 92ba374 into master Apr 1, 2023
@tigerwill90
tigerwill90 deleted the route-format-declaration branch April 1, 2023 12:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant