Fix ambiguous routing issues by teaching router about reserved words
The Rails router interpreted that URL as
gitlab-org/gitlab-ce/blob/master/app/assets obviously doesn't exist, this request gets handled by the
*unmatched_route route, which renders 404. We see 422 instead because some Rails middleware sees the
.js extension and raises an error:
This will happen for any blob or tree URL that includes
tree in the path itself, because of Rails's greedy matching.
This MR "teaches" the router about reserved words using a constraint regex for
project_id that includes a negative lookahead for these reserved words, so that the router will not even try to parse the
project_id using those words.
This MR is so big because we need to construct appropriate regexes for the router to use, which the original design of
DynamicPathValidator did not allow for. I've refactored
DynamicPathValidator and extracted some of its previous responsibility into
Gitlab::PathRegex to give us the regexes we need, and hopefully make the whole thing easier to understand.
I think this issue was introduced by https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10413, because as far as I can see it exists on 9-2-stable but not 9-1-stable and because the issue seems related, but I cannot actually pinpoint the line in that MR that causes the issue, since it doesn't touch the routing files at all...
@reprazent Curious to hear your thoughts about the issue and my solution!