| 252 | } |
| 253 | |
| 254 | const middleware = async (event: H3Event, next: () => any) => { |
| 255 | let originalPathname: string | undefined; |
| 256 | let originalEventPath: string | undefined; |
| 257 | let hadEventPath = false; |
| 258 | const restoreOriginalPath = () => { |
| 259 | if (originalPathname !== undefined) { |
| 260 | try { |
| 261 | event.url.pathname = originalPathname; |
| 262 | } catch { |
| 263 | // ignore |
| 264 | } |
| 265 | originalPathname = undefined; |
| 266 | } |
| 267 | if (hadEventPath) { |
| 268 | try { |
| 269 | (event as any).path = originalEventPath; |
| 270 | } catch { |
| 271 | // ignore |
| 272 | } |
| 273 | } else { |
| 274 | try { |
| 275 | delete (event as any).path; |
| 276 | } catch { |
| 277 | // ignore |
| 278 | } |
| 279 | } |
| 280 | }; |
| 281 | if (path) { |
| 282 | const reqPath = event.url?.pathname ?? ""; |
| 283 | const match = resolveMountMatch(reqPath, path); |
| 284 | if (!match) { |
| 285 | return next(); |
| 286 | } |
| 287 | // Strip the mount prefix from event.url.pathname so handlers that |
| 288 | // dispatch sub-routes can read `event.path` (or `event.url.pathname`) |
| 289 | // and see the path RELATIVE to their mount point — matching h3 v1's |
| 290 | // `app.use(path, handler)` semantics. |
| 291 | const eventAny = event as any; |
| 292 | hadEventPath = "path" in eventAny; |
| 293 | originalEventPath = eventAny.path; |
| 294 | try { |
| 295 | originalPathname = event.url.pathname; |
| 296 | // Save the full path in context so handlers that need the original URL |
| 297 | // (e.g. Better Auth, which extracts its own basePath prefix) can |
| 298 | // reconstruct a Request with the un-stripped URL. |
| 299 | eventAny.context = eventAny.context ?? {}; |
| 300 | eventAny.context._mountedPathname = originalPathname; |
| 301 | eventAny.context._mountPrefix = match.mountPath; |
| 302 | event.url.pathname = match.strippedPath; |
| 303 | eventAny.path = `${match.strippedPath}${event.url.search || ""}`; |
| 304 | } catch { |
| 305 | // event.url is read-only on some runtimes — fall through. Handlers |
| 306 | // that don't depend on prefix stripping (most of them) still work. |
| 307 | } |
| 308 | } |
| 309 | try { |
| 310 | const result = await handler(event); |
| 311 | if (result === undefined) { |