| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960 |
- import isPlainObject from 'is-plain-obj';
- import { Debug } from './debug.js';
- const debug = Debug.extend('router');
- export async function getTarget(req, res, config) {
- let newTarget;
- const router = config.router;
- if (isPlainObject(router)) {
- newTarget = getTargetFromProxyTable(req, router);
- }
- else if (typeof router === 'function') {
- newTarget = await router(req, res, config);
- }
- return newTarget;
- }
- function getTargetFromProxyTable(req, table) {
- let result;
- const host = req.headers.host ?? '';
- const path = req.url ?? '';
- for (const [key, value] of Object.entries(table)) {
- if (containsPath(key)) {
- if (isHostAndPathKey(key)) {
- const [keyHost, keyPath] = splitHostAndPathKey(key);
- // SECURITY: host+path keys must match exact host + path prefix.
- if (host === keyHost && path.startsWith(keyPath)) {
- // match 'localhost:3000/api'
- result = value;
- debug('match: "%s" -> "%s"', key, result);
- break;
- }
- }
- else {
- if (path.startsWith(key)) {
- // match '/api'
- result = value;
- debug('match: "%s" -> "%s"', key, result);
- break;
- }
- }
- }
- else {
- if (key === host) {
- // match 'localhost:3000'
- result = value;
- debug('match: "%s" -> "%s"', host, result);
- break;
- }
- }
- }
- return result;
- }
- function containsPath(v) {
- return v.indexOf('/') > -1;
- }
- function isHostAndPathKey(v) {
- return containsPath(v) && !v.startsWith('/');
- }
- function splitHostAndPathKey(v) {
- const firstSlash = v.indexOf('/');
- return [v.slice(0, firstSlash), v.slice(firstSlash)];
- }
|