UNPKG

@tdb/web

Version:

Common condiguration for serving a web-site and testing web-based UI components.

63 lines (50 loc) 1.55 kB
import { Request, Response, NextFunction } from 'express'; import { parse as parseUrl, Url } from 'url'; import { RedirectPath } from './types'; import { url } from './common'; export function redirectHandler( fromPath: string, toPath: RedirectPath | string, ) { const route = url.Route.create(fromPath); return (req: Request, res: Response, next: NextFunction) => { // Only allow GET requests. if (req.method !== 'GET') { return next(); } // Match the URL. const requestUrl = parseUrl(req.url, true); const pathname = requestUrl.pathname; if (route.isMatch(pathname)) { const params = route.params(pathname); // Build the URL. const value = typeof toPath === 'function' ? toPath({ url: requestUrl, params }) : toPath; const url = parseUrl(value, true); let path = url.pathname || ''; const hasQuery = url.search || requestUrl.search; if (hasQuery) { const query = toMergedQuery(url, requestUrl); path = `${path}?${query}`; } // Redirect to the new URL. return res.redirect(path); } return next(); }; } /** * INTERNAL */ const toMergedQuery = (...urls: Url[]) => { const merged = urls.reduce((acc, url) => { const query = url.query as object; return { ...acc, ...query }; }, {}); const toQuery = (key: string, value: string) => value ? `${key}=${value}` : key; const query = Object.keys(merged).map(key => toQuery(key, merged[key])); return query.join('&'); };