| 111 | } |
| 112 | |
| 113 | match(method: Method, url: URL): RouteResult<T> { |
| 114 | const result: RouteResult<T> = { |
| 115 | params: Object.create(null), |
| 116 | item: null, |
| 117 | methodMatch: false, |
| 118 | pattern: null, |
| 119 | }; |
| 120 | |
| 121 | let pathname = url.pathname; |
| 122 | let staticMatch = this.#statics.get(pathname); |
| 123 | |
| 124 | // Try alternate trailing slash form if no exact match found. |
| 125 | // Routes may be registered with or without trailing slashes, |
| 126 | // and requests may arrive in either form (e.g. when using |
| 127 | // trailingSlashes("always")). |
| 128 | if (staticMatch === undefined && pathname !== "/") { |
| 129 | const alt = pathname.endsWith("/") |
| 130 | ? pathname.slice(0, -1) |
| 131 | : pathname + "/"; |
| 132 | const altMatch = this.#statics.get(alt); |
| 133 | if (altMatch !== undefined) { |
| 134 | staticMatch = altMatch; |
| 135 | pathname = alt; |
| 136 | } |
| 137 | } |
| 138 | |
| 139 | if (staticMatch !== undefined) { |
| 140 | result.pattern = pathname; |
| 141 | |
| 142 | let item = staticMatch.byMethod[method]; |
| 143 | if (method === "HEAD" && item === null) { |
| 144 | item = staticMatch.byMethod.GET; |
| 145 | } |
| 146 | if (item !== null) { |
| 147 | result.methodMatch = true; |
| 148 | result.item = item; |
| 149 | } |
| 150 | |
| 151 | return result; |
| 152 | } |
| 153 | |
| 154 | for (let i = 0; i < this.#dynamicArr.length; i++) { |
| 155 | const route = this.#dynamicArr[i]; |
| 156 | |
| 157 | const match = route.pattern.exec(url); |
| 158 | if (match === null) continue; |
| 159 | |
| 160 | result.pattern = route.pattern.pathname; |
| 161 | |
| 162 | let item = route.byMethod[method]; |
| 163 | if (method === "HEAD" && item === null) { |
| 164 | item = route.byMethod.GET; |
| 165 | } |
| 166 | |
| 167 | if (item !== null) { |
| 168 | result.methodMatch = true; |
| 169 | result.item = item; |
| 170 | |