rsnext/packages/next/next-server/server/router.ts
Tim Neutkens 6a2c16a945
Update router to have only one route traverse pass (#9435)
* Fix next-news inconsistent return type

* Add failing test for static file rewrite

* Revert "Fix next-news inconsistent return type"

This reverts commit b66e76fb86061e45741c3c4bb9296a0874900f76.

* Add failing test for double redirect

* Fix bug in matcher when having multiple redirects

* Remove custom traversal in favor of router handling it

* Update next-server.ts

* Update router.ts

* Temporarily disable test

* Don't deeply resolve redirects

* Support combined parameters + query passing

* Make sure params are correctly passed in

* Add test for hash in route
2019-11-17 16:12:48 -08:00

70 lines
1.6 KiB
TypeScript

import { IncomingMessage, ServerResponse } from 'http'
import { UrlWithParsedQuery } from 'url'
import pathMatch from './lib/path-match'
export const route = pathMatch()
export type Params = { [param: string]: any }
export type RouteMatch = (pathname: string | undefined) => false | Params
type RouteResult = {
finished: boolean
pathname?: string
}
export type Route = {
match: RouteMatch
type: string
statusCode?: number
name: string
fn: (
req: IncomingMessage,
res: ServerResponse,
params: Params,
parsedUrl: UrlWithParsedQuery
) => Promise<RouteResult> | RouteResult
}
export default class Router {
routes: Route[]
constructor(routes: Route[] = []) {
this.routes = routes
}
add(route: Route) {
this.routes.unshift(route)
}
async execute(
req: IncomingMessage,
res: ServerResponse,
parsedUrl: UrlWithParsedQuery
): Promise<boolean> {
let parsedUrlUpdated = parsedUrl
for (const route of this.routes) {
const newParams = route.match(parsedUrlUpdated.pathname)
// Check if the match function matched
if (newParams) {
// Combine parameters and querystring
if (route.type === 'rewrite' || route.type === 'redirect') {
parsedUrlUpdated.query = { ...parsedUrlUpdated.query, ...newParams }
}
const result = await route.fn(req, res, newParams, parsedUrlUpdated)
// The response was handled
if (result.finished) {
return true
}
if (result.pathname) {
parsedUrlUpdated.pathname = result.pathname
}
}
}
return false
}
}