Skip to content

Correctly handle trailing slashes in URITemplateRouter#2464

Merged
jviotti merged 4 commits into
mainfrom
router-slashes
May 31, 2026
Merged

Correctly handle trailing slashes in URITemplateRouter#2464
jviotti merged 4 commits into
mainfrom
router-slashes

Conversation

@jviotti
Copy link
Copy Markdown
Member

@jviotti jviotti commented May 30, 2026

Signed-off-by: Juan Cruz Viotti jv@jviotti.com

Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
@augmentcode
Copy link
Copy Markdown

augmentcode Bot commented May 30, 2026

🤖 Augment PR Summary

Summary: This PR makes trailing slashes a first-class, distinct part of route matching for URITemplateRouter and its serialized URITemplateRouterView.

Changes:

  • When registering templates that end in /, the router now creates an explicit empty literal child node to represent the trailing-slash variant.
  • During matching, an empty final segment caused by a trailing slash is no longer rejected outright; it can resolve to that empty literal child when present.
  • Mirrors the same trailing-slash matching behavior in URITemplateRouterView::match(), including safety checks around node ranges.
  • Adds extensive unit tests for both router implementations covering bare vs slashed paths, variables, base paths, template trailing-slash normalization, and ensuring internal double-slashes in requests still do not match.

Technical Notes: The approach preserves strictness for internal empty segments (double slashes) while enabling distinct route registrations for /foo vs /foo/.

🤖 Was this summary useful? React with 👍 or 👎

Copy link
Copy Markdown

@augmentcode augmentcode Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. 1 suggestion posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

Comment thread src/core/uritemplate/uritemplate_router.cc Outdated
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 4 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/core/uritemplate/uritemplate_router.cc">

<violation number="1" location="src/core/uritemplate/uritemplate_router.cc:494">
P2: Templates consisting only of slashes (e.g. `"////"`) will leave `current == nullptr` after the parsing loop, causing both this trailing-slash block and the final registration block to be skipped. The `add()` call silently does nothing—no route is registered and no error is raised. Consider normalizing slash-only templates to the existing `"/"` root handling or explicitly rejecting them to avoid surprising no-op registrations.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

current = &find_or_create_literal_child(literals, "");
}

if (!absorbed && current != nullptr && current != base_path_end &&
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Templates consisting only of slashes (e.g. "////") will leave current == nullptr after the parsing loop, causing both this trailing-slash block and the final registration block to be skipped. The add() call silently does nothing—no route is registered and no error is raised. Consider normalizing slash-only templates to the existing "/" root handling or explicitly rejecting them to avoid surprising no-op registrations.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/core/uritemplate/uritemplate_router.cc, line 494:

<comment>Templates consisting only of slashes (e.g. `"////"`) will leave `current == nullptr` after the parsing loop, causing both this trailing-slash block and the final registration block to be skipped. The `add()` call silently does nothing—no route is registered and no error is raised. Consider normalizing slash-only templates to the existing `"/"` root handling or explicitly rejecting them to avoid surprising no-op registrations.</comment>

<file context>
@@ -491,6 +491,11 @@ auto URITemplateRouter::add(const std::string_view uri_template,
     current = &find_or_create_literal_child(literals, "");
   }
 
+  if (!absorbed && current != nullptr && current != base_path_end &&
+      uri_template.size() > 1 && uri_template.back() == '/') {
+    current = &find_or_create_literal_child(current->literals, "");
</file context>

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark (macos/llvm)

Details
Benchmark suite Current: fe58667 Previous: ec3ab52 Ratio
Regex_Lower_S_Or_Upper_S_Asterisk 2.023008927224815 ns/iter 2.024502094778693 ns/iter 1.00
Regex_Caret_Lower_S_Or_Upper_S_Asterisk_Dollar 1.7661190441047656 ns/iter 1.6226946302130283 ns/iter 1.09
Regex_Period_Asterisk 1.699431746937724 ns/iter 1.6580394489985497 ns/iter 1.02
Regex_Group_Period_Asterisk_Group 1.7041911377307704 ns/iter 1.658989262174867 ns/iter 1.03
Regex_Period_Plus 2.0396430433685344 ns/iter 2.020224328612864 ns/iter 1.01
Regex_Period 2.105180646541632 ns/iter 1.9961204882865218 ns/iter 1.05
Regex_Caret_Period_Plus_Dollar 2.0456668919574366 ns/iter 1.9791187122442282 ns/iter 1.03
Regex_Caret_Group_Period_Plus_Group_Dollar 2.103878436879067 ns/iter 2.0273622891664287 ns/iter 1.04
Regex_Caret_Period_Asterisk_Dollar 1.7327891046745372 ns/iter 1.6525958240776746 ns/iter 1.05
Regex_Caret_Group_Period_Asterisk_Group_Dollar 1.8006522328361179 ns/iter 1.6587680795419664 ns/iter 1.09
Regex_Caret_X_Hyphen 6.249767841218333 ns/iter 5.77392345407608 ns/iter 1.08
Regex_Period_Md_Dollar 18.102403983783482 ns/iter 15.932790853667324 ns/iter 1.14
Regex_Caret_Slash_Period_Asterisk 4.878141143336687 ns/iter 4.08445048290761 ns/iter 1.19
Regex_Caret_Period_Range_Dollar 2.0726259501424433 ns/iter 1.9292850326935878 ns/iter 1.07
Regex_Nested_Backtrack 25.25843390412393 ns/iter 24.44234500873663 ns/iter 1.03
JSON_Array_Of_Objects_Unique 434.62103532893866 ns/iter 415.0942589656784 ns/iter 1.05
JSON_Parse_1 4876.104303214185 ns/iter 5260.747110241713 ns/iter 0.93
JSON_Parse_Real 7269.621522288123 ns/iter 7398.416019487728 ns/iter 0.98
JSON_Parse_Decimal 8350.659232277312 ns/iter 8984.807549811656 ns/iter 0.93
JSON_Parse_Schema_ISO_Language 3218706.986111194 ns/iter 3335873.2328045256 ns/iter 0.96
JSON_Fast_Hash_Helm_Chart_Lock 60.431038467954245 ns/iter 58.14016170613144 ns/iter 1.04
JSON_Equality_Helm_Chart_Lock 140.95724412628405 ns/iter 131.4450696727289 ns/iter 1.07
JSON_Divisible_By_Decimal 178.8456898837942 ns/iter 164.32875094178561 ns/iter 1.09
JSON_String_Equal/10 6.8881782950220485 ns/iter 6.482598528223076 ns/iter 1.06
JSON_String_Equal/100 6.617389147723418 ns/iter 6.031828840060782 ns/iter 1.10
JSON_String_Equal_Small_By_Perfect_Hash/10 0.7729710341586941 ns/iter 0.7241673428200286 ns/iter 1.07
JSON_String_Equal_Small_By_Runtime_Perfect_Hash/10 3.3959001655985257 ns/iter 3.1572893132010726 ns/iter 1.08
JSON_String_Fast_Hash/10 2.481380038007788 ns/iter 2.2520024413241675 ns/iter 1.10
JSON_String_Fast_Hash/100 2.0308805591250914 ns/iter 1.9296559995851663 ns/iter 1.05
JSON_String_Key_Hash/10 1.3488899997919535 ns/iter 1.4072655347764071 ns/iter 0.96
JSON_String_Key_Hash/100 2.158549042199146 ns/iter 2.1426865554239862 ns/iter 1.01
JSON_Object_Defines_Miss_Same_Length 2.3797213949498697 ns/iter 2.380285213979885 ns/iter 1.00
JSON_Object_Defines_Miss_Too_Small 2.379841484752044 ns/iter 2.243377851821152 ns/iter 1.06
JSON_Object_Defines_Miss_Too_Large 2.437302950919509 ns/iter 2.3524393517390756 ns/iter 1.04
Pointer_Object_Traverse 14.810218799781264 ns/iter 13.756642717500945 ns/iter 1.08
Pointer_Object_Try_Traverse 23.473641206482988 ns/iter 23.646351813764905 ns/iter 0.99
Pointer_Push_Back_Pointer_To_Weak_Pointer 151.81994761424954 ns/iter 150.99408941770733 ns/iter 1.01
Pointer_Walker_Schema_ISO_Language 4036240.1271675806 ns/iter 4886306.352564163 ns/iter 0.83
Pointer_Maybe_Tracked_Deeply_Nested/0 985364.3009985187 ns/iter 1019254.6159527024 ns/iter 0.97
Pointer_Maybe_Tracked_Deeply_Nested/1 1350775.4237287708 ns/iter 1512906.539525727 ns/iter 0.89
Pointer_Position_Tracker_Get_Deeply_Nested 348.4564696225236 ns/iter 362.9705765035049 ns/iter 0.96
URITemplateRouter_Create 25255.021007547068 ns/iter 23522.33159509132 ns/iter 1.07
URITemplateRouter_Match 194.81059879585123 ns/iter 165.3221143854459 ns/iter 1.18
URITemplateRouter_Match_BasePath 212.23707241819008 ns/iter 186.12963869089097 ns/iter 1.14
URITemplateRouterView_Restore 9899.488582991575 ns/iter 8885.733453117817 ns/iter 1.11
URITemplateRouterView_Match 131.04342738511133 ns/iter 122.70000628756182 ns/iter 1.07
URITemplateRouterView_Match_BasePath 158.97165816559607 ns/iter 139.91648613721765 ns/iter 1.14
URITemplateRouterView_Arguments 409.241523009635 ns/iter 396.6329213574847 ns/iter 1.03
JSONL_Parse_Large 13601824.519230813 ns/iter 12415846.982758561 ns/iter 1.10
JSONL_Parse_Large_GZIP 14316691.130434461 ns/iter 13328737.415094418 ns/iter 1.07
HTML_Build_Table_100000 79428109.37500155 ns/iter 63142602.272726186 ns/iter 1.26
HTML_Render_Table_100000 3639106.3953490546 ns/iter 3078560.1660230765 ns/iter 1.18
GZIP_Compress_ISO_Language_Set_3_Locations 30531503.458332073 ns/iter 26489899.703704026 ns/iter 1.15
GZIP_Decompress_ISO_Language_Set_3_Locations 5829206.451128152 ns/iter 6008124.1776319565 ns/iter 0.97
GZIP_Compress_ISO_Language_Set_3_Schema 1590704.09930711 ns/iter 1446627.6101010675 ns/iter 1.10
GZIP_Decompress_ISO_Language_Set_3_Schema 299158.6121437219 ns/iter 262888.79688713275 ns/iter 1.14

This comment was automatically generated by workflow using github-action-benchmark.

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark (linux/llvm)

Details
Benchmark suite Current: fe58667 Previous: ec3ab52 Ratio
Regex_Lower_S_Or_Upper_S_Asterisk 2.4616517971175127 ns/iter 2.1818951985205097 ns/iter 1.13
Regex_Caret_Lower_S_Or_Upper_S_Asterisk_Dollar 2.4659491035933434 ns/iter 2.180159705101779 ns/iter 1.13
Regex_Period_Asterisk 2.4634833217136625 ns/iter 2.1789166576770462 ns/iter 1.13
Regex_Group_Period_Asterisk_Group 2.4626111077406914 ns/iter 2.179685384743455 ns/iter 1.13
Regex_Period_Plus 3.8678756251777027 ns/iter 2.805794336181445 ns/iter 1.38
Regex_Period 3.8703167487425194 ns/iter 2.802327882070371 ns/iter 1.38
Regex_Caret_Period_Plus_Dollar 3.5173727022926022 ns/iter 2.491886400660958 ns/iter 1.41
Regex_Caret_Group_Period_Plus_Group_Dollar 3.5186582300692986 ns/iter 2.5019042786307346 ns/iter 1.41
Regex_Caret_Period_Asterisk_Dollar 2.814702697980883 ns/iter 3.425730659514792 ns/iter 0.82
Regex_Caret_Group_Period_Asterisk_Group_Dollar 2.8582897500759983 ns/iter 3.4268878127565765 ns/iter 0.83
Regex_Caret_X_Hyphen 6.6876904425255566 ns/iter 6.542778493195267 ns/iter 1.02
Regex_Period_Md_Dollar 27.45088442848014 ns/iter 27.712061374264024 ns/iter 0.99
Regex_Caret_Slash_Period_Asterisk 7.384502036732324 ns/iter 5.916157770375355 ns/iter 1.25
Regex_Caret_Period_Range_Dollar 3.8686855856057196 ns/iter 2.8213124758063928 ns/iter 1.37
Regex_Nested_Backtrack 37.56783931849595 ns/iter 36.84158463997745 ns/iter 1.02
JSON_Array_Of_Objects_Unique 476.194560197109 ns/iter 441.91341432627377 ns/iter 1.08
JSON_Parse_1 6825.46640027289 ns/iter 6880.783280729001 ns/iter 0.99
JSON_Parse_Real 11090.89828503016 ns/iter 11743.223119899401 ns/iter 0.94
JSON_Parse_Decimal 11889.738962817944 ns/iter 11867.479096082561 ns/iter 1.00
JSON_Parse_Schema_ISO_Language 4028159.8735634424 ns/iter 3846928.4780225093 ns/iter 1.05
JSON_Fast_Hash_Helm_Chart_Lock 79.17632229549399 ns/iter 71.69389344398105 ns/iter 1.10
JSON_Equality_Helm_Chart_Lock 190.29790022019586 ns/iter 168.03592973849243 ns/iter 1.13
JSON_Divisible_By_Decimal 251.69539010157786 ns/iter 249.37015070516483 ns/iter 1.01
JSON_String_Equal/10 6.3309699463966815 ns/iter 6.5510270876904 ns/iter 0.97
JSON_String_Equal/100 7.038424830080263 ns/iter 7.168424252824143 ns/iter 0.98
JSON_String_Equal_Small_By_Perfect_Hash/10 1.0554625684248085 ns/iter 0.9403617507063093 ns/iter 1.12
JSON_String_Equal_Small_By_Runtime_Perfect_Hash/10 12.491342872672552 ns/iter 15.003911381573829 ns/iter 0.83
JSON_String_Fast_Hash/10 3.168123551171244 ns/iter 3.1156291865137034 ns/iter 1.02
JSON_String_Fast_Hash/100 3.1674530826069764 ns/iter 3.118740196207803 ns/iter 1.02
JSON_String_Key_Hash/10 2.463646888604096 ns/iter 2.254980018655048 ns/iter 1.09
JSON_String_Key_Hash/100 8.088166383047378 ns/iter 9.048933205941642 ns/iter 0.89
JSON_Object_Defines_Miss_Same_Length 2.9210692380190473 ns/iter 2.675792387882199 ns/iter 1.09
JSON_Object_Defines_Miss_Too_Small 2.908943290261587 ns/iter 2.648693070376156 ns/iter 1.10
JSON_Object_Defines_Miss_Too_Large 4.222746551728957 ns/iter 3.737377815996358 ns/iter 1.13
Pointer_Object_Traverse 25.773276145031915 ns/iter 24.66593928466631 ns/iter 1.04
Pointer_Object_Try_Traverse 29.231296547160262 ns/iter 28.30878387289857 ns/iter 1.03
Pointer_Push_Back_Pointer_To_Weak_Pointer 182.2520086494951 ns/iter 172.30818320331724 ns/iter 1.06
Pointer_Walker_Schema_ISO_Language 3108106.320175402 ns/iter 3017873.151898686 ns/iter 1.03
Pointer_Maybe_Tracked_Deeply_Nested/0 1465229.2748414613 ns/iter 1494415.7505330597 ns/iter 0.98
Pointer_Maybe_Tracked_Deeply_Nested/1 1799818.6640625726 ns/iter 1947394.326315601 ns/iter 0.92
Pointer_Position_Tracker_Get_Deeply_Nested 720.6474530790379 ns/iter 655.9889671869884 ns/iter 1.10
URITemplateRouter_Create 30744.3058582535 ns/iter 31454.410426370177 ns/iter 0.98
URITemplateRouter_Match 184.16422305504128 ns/iter 163.73479041536572 ns/iter 1.12
URITemplateRouter_Match_BasePath 218.79821128283652 ns/iter 187.1280947848351 ns/iter 1.17
URITemplateRouterView_Restore 8757.026009248033 ns/iter 7908.522688161386 ns/iter 1.11
URITemplateRouterView_Match 143.46762890497112 ns/iter 155.73423409923737 ns/iter 0.92
URITemplateRouterView_Match_BasePath 161.87153811950262 ns/iter 176.15727852075324 ns/iter 0.92
URITemplateRouterView_Arguments 455.2045666731441 ns/iter 443.3892682741375 ns/iter 1.03
JSONL_Parse_Large 11440337.709678538 ns/iter 12069510.189654654 ns/iter 0.95
JSONL_Parse_Large_GZIP 12753129.054544844 ns/iter 13318760.788461776 ns/iter 0.96
HTML_Build_Table_100000 91365886.37500153 ns/iter 67705282.18181549 ns/iter 1.35
HTML_Render_Table_100000 5342339.558139901 ns/iter 5144098.251851877 ns/iter 1.04
GZIP_Compress_ISO_Language_Set_3_Locations 36472759.15789363 ns/iter 34554012.949996606 ns/iter 1.06
GZIP_Decompress_ISO_Language_Set_3_Locations 4769470.904761875 ns/iter 4975955.789854711 ns/iter 0.96
GZIP_Compress_ISO_Language_Set_3_Schema 2106164.563253038 ns/iter 1908724.585830881 ns/iter 1.10
GZIP_Decompress_ISO_Language_Set_3_Schema 290569.2495847289 ns/iter 376834.0080385769 ns/iter 0.77

This comment was automatically generated by workflow using github-action-benchmark.

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark (windows/msvc)

Details
Benchmark suite Current: fe58667 Previous: ec3ab52 Ratio
Regex_Lower_S_Or_Upper_S_Asterisk 2.495573435271703 ns/iter 5.063208928571531 ns/iter 0.49
Regex_Caret_Lower_S_Or_Upper_S_Asterisk_Dollar 2.557992052429353 ns/iter 5.018043749999939 ns/iter 0.51
Regex_Period_Asterisk 2.6703641717230178 ns/iter 5.026991999999382 ns/iter 0.53
Regex_Group_Period_Asterisk_Group 2.619128570259878 ns/iter 5.016498885048308 ns/iter 0.52
Regex_Period_Plus 2.577010645020891 ns/iter 4.7049401890738025 ns/iter 0.55
Regex_Period 2.617123214285552 ns/iter 4.702228805138945 ns/iter 0.56
Regex_Caret_Period_Plus_Dollar 2.684839285714296 ns/iter 4.704632443805418 ns/iter 0.57
Regex_Caret_Group_Period_Plus_Group_Dollar 2.5726974999997765 ns/iter 4.705631260767012 ns/iter 0.55
Regex_Caret_Period_Asterisk_Dollar 2.628303211939169 ns/iter 5.016071000000011 ns/iter 0.52
Regex_Caret_Group_Period_Asterisk_Group_Dollar 2.6437514285711523 ns/iter 5.014747999999827 ns/iter 0.53
Regex_Caret_X_Hyphen 5.987791071429375 ns/iter 8.468091926481174 ns/iter 0.71
Regex_Period_Md_Dollar 31.632956297837715 ns/iter 46.13673986912622 ns/iter 0.69
Regex_Caret_Slash_Period_Asterisk 5.680167857144219 ns/iter 8.168189732141887 ns/iter 0.70
Regex_Caret_Period_Range_Dollar 2.7827455357142736 ns/iter 5.6485410714271564 ns/iter 0.49
Regex_Nested_Backtrack 42.806679687501514 ns/iter 58.52987500000089 ns/iter 0.73
JSON_Array_Of_Objects_Unique 414.6517813072986 ns/iter 515.5798000000686 ns/iter 0.80
JSON_Parse_1 9583.955428770772 ns/iter 11607.44821428596 ns/iter 0.83
JSON_Parse_Real 15223.502232143257 ns/iter 18473.67102904597 ns/iter 0.82
JSON_Parse_Decimal 16200.964285713684 ns/iter 17803.889311758787 ns/iter 0.91
JSON_Parse_Schema_ISO_Language 7633602.22222218 ns/iter 7610902.222222649 ns/iter 1.00
JSON_Fast_Hash_Helm_Chart_Lock 50.671200000010685 ns/iter 70.41036607142408 ns/iter 0.72
JSON_Equality_Helm_Chart_Lock 255.01321428570074 ns/iter 312.60468750003514 ns/iter 0.82
JSON_Divisible_By_Decimal 289.8148531332651 ns/iter 303.3738567663102 ns/iter 0.96
JSON_String_Equal/10 11.26375781250033 ns/iter 16.920099217055018 ns/iter 0.67
JSON_String_Equal/100 13.869439893437994 ns/iter 16.798853682151705 ns/iter 0.83
JSON_String_Equal_Small_By_Perfect_Hash/10 1.530919285030708 ns/iter 2.5110009352583216 ns/iter 0.61
JSON_String_Equal_Small_By_Runtime_Perfect_Hash/10 9.638899510538042 ns/iter 15.025214665063157 ns/iter 0.64
JSON_String_Fast_Hash/10 2.915562719309471 ns/iter 5.016791071428527 ns/iter 0.58
JSON_String_Fast_Hash/100 2.914691784413245 ns/iter 5.011173000000326 ns/iter 0.58
JSON_String_Key_Hash/10 2.927149150478493 ns/iter 5.7839289999992625 ns/iter 0.51
JSON_String_Key_Hash/100 13.731305965484836 ns/iter 16.7350389504326 ns/iter 0.82
JSON_Object_Defines_Miss_Same_Length 4.077635221394044 ns/iter 4.324309149854141 ns/iter 0.94
JSON_Object_Defines_Miss_Too_Small 3.5867257971666437 ns/iter 4.296978961166617 ns/iter 0.83
JSON_Object_Defines_Miss_Too_Large 3.8492857142864114 ns/iter 4.839793749998274 ns/iter 0.80
Pointer_Object_Traverse 41.406517956541066 ns/iter 61.10502678570892 ns/iter 0.68
Pointer_Object_Try_Traverse 53.14658647446765 ns/iter 71.14410714285566 ns/iter 0.75
Pointer_Push_Back_Pointer_To_Weak_Pointer 184.66359272302267 ns/iter 165.50857142857262 ns/iter 1.12
Pointer_Walker_Schema_ISO_Language 12902472.00000067 ns/iter 12333135.714283928 ns/iter 1.05
Pointer_Maybe_Tracked_Deeply_Nested/0 2382795.1807227265 ns/iter 2283674.621211999 ns/iter 1.04
Pointer_Maybe_Tracked_Deeply_Nested/1 4406499.374999839 ns/iter 3791164.245810083 ns/iter 1.16
Pointer_Position_Tracker_Get_Deeply_Nested 538.9665331906822 ns/iter 671.2837181770008 ns/iter 0.80
URITemplateRouter_Create 40315.17613603621 ns/iter 43414.74999999662 ns/iter 0.93
URITemplateRouter_Match 246.49912427464486 ns/iter 238.32827697231284 ns/iter 1.03
URITemplateRouter_Match_BasePath 269.9245325926454 ns/iter 274.0080413389215 ns/iter 0.99
URITemplateRouterView_Restore 24558.35537550405 ns/iter 32968.05803571041 ns/iter 0.74
URITemplateRouterView_Match 159.22397321429366 ns/iter 184.3962753925438 ns/iter 0.86
URITemplateRouterView_Match_BasePath 172.31346466386603 ns/iter 208.81019826740183 ns/iter 0.83
URITemplateRouterView_Arguments 417.31067904408565 ns/iter 519.9370535714414 ns/iter 0.80
JSONL_Parse_Large 28702474.999998152 ns/iter 35947726.31578579 ns/iter 0.80
JSONL_Parse_Large_GZIP 28260188.000003837 ns/iter 35531604.99999421 ns/iter 0.80
HTML_Build_Table_100000 94764557.14285032 ns/iter 92168128.57143201 ns/iter 1.03
HTML_Render_Table_100000 12161615.624997068 ns/iter 7685578.888890632 ns/iter 1.58
GZIP_Compress_ISO_Language_Set_3_Locations 40483988.235283665 ns/iter 41013641.176465064 ns/iter 0.99
GZIP_Decompress_ISO_Language_Set_3_Locations 13149614.000003567 ns/iter 10780146.87499973 ns/iter 1.22
GZIP_Compress_ISO_Language_Set_3_Schema 2290301.003344467 ns/iter 2299320.4013376674 ns/iter 1.00
GZIP_Decompress_ISO_Language_Set_3_Schema 740201.0714287143 ns/iter 683295.7142857967 ns/iter 1.08

This comment was automatically generated by workflow using github-action-benchmark.

Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 4 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/core/uritemplate/uritemplate_router.cc">

<violation number="1" location="src/core/uritemplate/uritemplate_router.cc:494">
P2: Templates consisting only of slashes (e.g. `"////"`) will leave `current == nullptr` after the parsing loop, causing both this trailing-slash block and the final registration block to be skipped. The `add()` call silently does nothing—no route is registered and no error is raised. Consider normalizing slash-only templates to the existing `"/"` root handling or explicitly rejecting them to avoid surprising no-op registrations.</violation>
</file>

<file name="src/core/uritemplate/uritemplate_router_view.cc">

<violation number="1" location="src/core/uritemplate/uritemplate_router_view.cc:505">
P2: This introduces a behavioral regression by rejecting non-leading-slash paths that were previously matchable. Keep optional leading-slash handling unless the API contract was intentionally tightened.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment on lines +505 to +511
if (path.front() != '/') {
return finalize_match(otherwise_context, 0, 0);
}

// Walk the trie, matching each path segment
std::uint32_t current_node = 0;
const char *position = path.data();
const char *const path_end = position + path.size();
const char *position = path.data() + 1;
const char *const path_end = path.data() + path.size();
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: This introduces a behavioral regression by rejecting non-leading-slash paths that were previously matchable. Keep optional leading-slash handling unless the API contract was intentionally tightened.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/core/uritemplate/uritemplate_router_view.cc, line 505:

<comment>This introduces a behavioral regression by rejecting non-leading-slash paths that were previously matchable. Keep optional leading-slash handling unless the API contract was intentionally tightened.</comment>

<file context>
@@ -497,102 +497,46 @@ auto URITemplateRouterView::match(
-    }
-    return finalize_match(otherwise_context, nodes[match].identifier,
-                          nodes[match].context);
+  if (path.front() != '/') {
+    return finalize_match(otherwise_context, 0, 0);
   }
</file context>
Suggested change
if (path.front() != '/') {
return finalize_match(otherwise_context, 0, 0);
}
// Walk the trie, matching each path segment
std::uint32_t current_node = 0;
const char *position = path.data();
const char *const path_end = position + path.size();
const char *position = path.data() + 1;
const char *const path_end = path.data() + path.size();
const char *position = path.data();
const char *const path_end = path.data() + path.size();
if (position < path_end && *position == '/') {
++position;
}
std::uint32_t current_node = 0;

Comment thread src/core/uritemplate/uritemplate_router.cc Outdated
jviotti added 2 commits May 30, 2026 19:26
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark (linux/gcc)

Details
Benchmark suite Current: fe58667 Previous: ec3ab52 Ratio
GZIP_Compress_ISO_Language_Set_3_Locations 40978874.529407546 ns/iter 40246850.99999956 ns/iter 1.02
GZIP_Decompress_ISO_Language_Set_3_Locations 4545778.168831434 ns/iter 4469827.700636936 ns/iter 1.02
GZIP_Compress_ISO_Language_Set_3_Schema 2298935.9703945853 ns/iter 2287643.9444444836 ns/iter 1.00
GZIP_Decompress_ISO_Language_Set_3_Schema 325861.3465804065 ns/iter 290978.5305105796 ns/iter 1.12
HTML_Build_Table_100000 72220575.4000015 ns/iter 70553887.40000126 ns/iter 1.02
HTML_Render_Table_100000 2093078.8411212412 ns/iter 1980060.355113525 ns/iter 1.06
JSONL_Parse_Large 14784540.39583473 ns/iter 14514723.000000358 ns/iter 1.02
JSONL_Parse_Large_GZIP 16090292.930230556 ns/iter 15828424.545454502 ns/iter 1.02
URITemplateRouter_Create 29632.323889382635 ns/iter 30373.505374945646 ns/iter 0.98
URITemplateRouter_Match 158.8795923901786 ns/iter 164.2702134483191 ns/iter 0.97
URITemplateRouter_Match_BasePath 191.48694657732196 ns/iter 186.3998845964014 ns/iter 1.03
URITemplateRouterView_Restore 8809.67715137081 ns/iter 8330.095001784768 ns/iter 1.06
URITemplateRouterView_Match 124.56188710853715 ns/iter 136.35611286556787 ns/iter 0.91
URITemplateRouterView_Match_BasePath 143.68711894200177 ns/iter 161.28537396352758 ns/iter 0.89
URITemplateRouterView_Arguments 450.3365378925255 ns/iter 459.94505475722065 ns/iter 0.98
Pointer_Object_Traverse 34.22177292537214 ns/iter 33.69345384623382 ns/iter 1.02
Pointer_Object_Try_Traverse 22.254433462974525 ns/iter 22.129552990360715 ns/iter 1.01
Pointer_Push_Back_Pointer_To_Weak_Pointer 151.43738805572866 ns/iter 165.71726425943783 ns/iter 0.91
Pointer_Walker_Schema_ISO_Language 3516966.05527659 ns/iter 3505436.3283582767 ns/iter 1.00
Pointer_Maybe_Tracked_Deeply_Nested/0 1869393.4545454762 ns/iter 1815058.758530138 ns/iter 1.03
Pointer_Maybe_Tracked_Deeply_Nested/1 1868548.1443852305 ns/iter 1825935.0779221205 ns/iter 1.02
Pointer_Position_Tracker_Get_Deeply_Nested 547.8528765068098 ns/iter 586.6141219893663 ns/iter 0.93
JSON_Array_Of_Objects_Unique 428.0450220395496 ns/iter 400.76779037386865 ns/iter 1.07
JSON_Parse_1 9685.083944275877 ns/iter 9531.357068416528 ns/iter 1.02
JSON_Parse_Real 13146.649595483763 ns/iter 13280.779165092867 ns/iter 0.99
JSON_Parse_Decimal 16960.177144520345 ns/iter 17189.772510918243 ns/iter 0.99
JSON_Parse_Schema_ISO_Language 5650549.000000037 ns/iter 5797468.688524811 ns/iter 0.97
JSON_Fast_Hash_Helm_Chart_Lock 61.319224807579666 ns/iter 53.13013618205252 ns/iter 1.15
JSON_Equality_Helm_Chart_Lock 168.62962920141896 ns/iter 183.89519302402385 ns/iter 0.92
JSON_Divisible_By_Decimal 229.4377315853291 ns/iter 228.16325305900105 ns/iter 1.01
JSON_String_Equal/10 6.113855980974136 ns/iter 6.0304009538638175 ns/iter 1.01
JSON_String_Equal/100 6.847805779373822 ns/iter 6.786013520193552 ns/iter 1.01
JSON_String_Equal_Small_By_Perfect_Hash/10 0.7145542004214187 ns/iter 0.7153038266415845 ns/iter 1.00
JSON_String_Equal_Small_By_Runtime_Perfect_Hash/10 21.937511118960394 ns/iter 21.936884587443792 ns/iter 1.00
JSON_String_Fast_Hash/10 1.7581439500227796 ns/iter 1.05550368558879 ns/iter 1.67
JSON_String_Fast_Hash/100 1.7599247939571605 ns/iter 1.055418255797365 ns/iter 1.67
JSON_String_Key_Hash/10 1.0852052890673884 ns/iter 1.759972436258043 ns/iter 0.62
JSON_String_Key_Hash/100 15.027115821109158 ns/iter 14.759185388944937 ns/iter 1.02
JSON_Object_Defines_Miss_Same_Length 3.8683673544801507 ns/iter 3.867522214179814 ns/iter 1.00
JSON_Object_Defines_Miss_Too_Small 3.521837861039072 ns/iter 4.221635906068492 ns/iter 0.83
JSON_Object_Defines_Miss_Too_Large 4.21980136992231 ns/iter 3.5158405047285846 ns/iter 1.20
Regex_Lower_S_Or_Upper_S_Asterisk 0.7034950943446739 ns/iter 1.0554518104611355 ns/iter 0.67
Regex_Caret_Lower_S_Or_Upper_S_Asterisk_Dollar 0.7038226686346973 ns/iter 1.055285192614705 ns/iter 0.67
Regex_Period_Asterisk 1.0700053981630546 ns/iter 0.7040351512679569 ns/iter 1.52
Regex_Group_Period_Asterisk_Group 1.055114891206321 ns/iter 0.7038081104183351 ns/iter 1.50
Regex_Period_Plus 0.7031149443758484 ns/iter 1.0551777434566731 ns/iter 0.67
Regex_Period 0.7036028877253467 ns/iter 1.0547646148031877 ns/iter 0.67
Regex_Caret_Period_Plus_Dollar 1.055940190639057 ns/iter 0.7039143857172082 ns/iter 1.50
Regex_Caret_Group_Period_Plus_Group_Dollar 1.0549237365434883 ns/iter 0.7039966788338103 ns/iter 1.50
Regex_Caret_Period_Asterisk_Dollar 0.704063867873698 ns/iter 1.056056810604562 ns/iter 0.67
Regex_Caret_Group_Period_Asterisk_Group_Dollar 0.705200095901354 ns/iter 1.0549441861634414 ns/iter 0.67
Regex_Caret_X_Hyphen 3.5163730389181826 ns/iter 4.221110498975404 ns/iter 0.83
Regex_Period_Md_Dollar 32.64964685247311 ns/iter 33.897866710576984 ns/iter 0.96
Regex_Caret_Slash_Period_Asterisk 4.570761948170884 ns/iter 3.872040830043942 ns/iter 1.18
Regex_Caret_Period_Range_Dollar 0.8393593346442372 ns/iter 1.0581146405032162 ns/iter 0.79
Regex_Nested_Backtrack 42.91636745864303 ns/iter 43.906220248947314 ns/iter 0.98

This comment was automatically generated by workflow using github-action-benchmark.

@jviotti jviotti merged commit fe6cf2d into main May 31, 2026
13 checks passed
@jviotti jviotti deleted the router-slashes branch May 31, 2026 00:19
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