How do Routes match requests?
Request matching basics
This article descibes how Proxyflare matches an incoming request to a Route in your Configuration using the concept of pathname score.
Let's test your intuition with a basic setup.
Proxyflare is installed on proxyflare.works with the Configuration below and a request arrives — GET https://proxyflare.works/api/users/john.
Each Route matches the incoming request. Which Route does Proxyflare run?
// incoming request: GET https://proxyflare.works/api/users/john
const routes: Route[] = [
{
from: { pattern: "proxyflare.works/api/*" },
...
},
{
from: { pattern: "proxyflare.works/api/users/*" },
...
},
]
The second route runs! But why?
Proxyflare sorts each Route by the pathname score of Route["from.pattern"]. The second route runs because it contains more pathname parts.
How pathname score works
If an incoming request matches multiple Routes, Proxyflare runs the Route with the higher pathname score. Every Route is assigned a pathname score using the value of Route["from.pattern"].
Assigning pathname depth
Pathname score increases with pathname depth. The more forward-slash / separated path slugs in Route["from.pattern"], the higher the rank.
For example, Route["from.pattern"]=ex.com/shallow/deeper has a pathname depth of two with path slugs shallow and deeper.
| Pathname depth | Pathname score | Route["from.pattern"] |
|---|---|---|
| 3 | 3 | ex.com/shallow/deeper/deep |
| 2 | 2 | ex.com/shallow/deeper |
| 1 | 1 | ex.com/shallow |
Breaking pathname depth ties
Given two patterns with the same pathname depth, rank is allocated by last slug length.
For example, given Route["from.pattern"]=ex.com/shallow/deep and Route["from.pattern"]=ex.com/shallow/deeper, the latter wins because deeper is longer slug than deep.
| Pathname depth | Last slug length | Pathname score | Route["from.pattern"] |
|---|---|---|---|
| 2 | 6 | 2 | ex.com/shallow/deeper |
| 2 | 4 | 1 | ex.com/shallow/deep |
Proxyflare supports wildcard patterns for matching subrequests on a particular pathname. Some pathname patterns would be identical when wildcards are removed. In this case, pattern type is used to break the tie:
- Absolute path
ex.com/shallow - Inline wildcard
ex.com/shallow* - Slash wildcard
ex.com/shallow/*
| Pathname depth | Last slug length | Pattern type | Pathname score | Route["from.pattern"] |
|---|---|---|---|---|
| 1 | 7 | absolute | 3 | ex.com/shallow |
| 1 | 7 | inline * | 2 | ex.com/shallow* |
| 1 | 7 | slash * | 1 | ex.com/shallow/* |
In other words, if multiple Routes are identical after wildcards are removed, the absolute path outranks the inline wildcard and the inline wildcard outranks the slash wildcard.
The Route with the highest pathname depth wins.
If multiple routes have the same pathname depth, the longer last path slug wins.
If multiple routes have the same last path slug after removing wildcards, absolute paths beat inline wildcards and inline wildcards beat slash wildcards.
The following table shows this ranking strategy with complex Route["from.pattern"]s listed by pathname score.
The last column shows an incoming request that would match each pattern.
| Pathname score | Route["from.pattern"] | Example Matching Request |
|---|---|---|
| 14 | ex.com/shallow/deeper | ex.com/shallow/deeper |
| 13 | ex.com/shallow/deeper* | ex.com/shallow/deeper-in |
| 12 | ex.com/shallow/deeper/* | ex.com/shallow/deeper/down |
| 11 | ex.com/shallow/deep | ex.com/shallow/deep |
| 10 | ex.com/shallow/deep* | ex.com/shallow/deep-in |
| 9 | ex.com/shallow/deep/* | ex.com/shallow/deep/down |
| 8 | ex.com/shallower | ex.com/shallower |
| 7 | ex.com/shallower* | ex.com/shallower-yet |
| 6 | ex.com/shallower/* | ex.com/shallower/still |
| 5 | ex.com/shallow | ex.com/shallow |
| 4 | ex.com/shallow* | ex.com/shallow-lakes |
| 3 | ex.com/shallow/* | ex.com/shallow/water |
| 2 | ex.com/ | ex.com/ |
| 1 | ex.com/* | ex.com/anything-still-unmatched |
Set the Configuration["global.debug"] flag to attach a x-proxyflare-proxied-pathname response header to matched requests. This debug header contains the matched pathname.