/*! * resolve-path * Copyright(c) 2014 Jonathan Ong * Copyright(c) 2015-2018 Douglas Christopher Wilson * MIT Licensed */ /** * ES Module 转换版本 * 路径解析工具,防止路径遍历攻击 */ import createError from 'http-errors'; import { join, normalize, resolve, sep } from 'path'; import pathIsAbsolute from 'path-is-absolute'; /** * 模块变量 * @private */ const UP_PATH_REGEXP = /(?:^|[\/])\.\.(?:[\/]|$)/; /** * 解析相对路径到根路径 * @param {string} rootPath - 根目录路径 * @param {string} relativePath - 相对路径 * @returns {string} 解析后的绝对路径 * @public */ function resolvePath(rootPath, relativePath) { let path = relativePath; let root = rootPath; // root是可选的,类似于root.resolve if (arguments.length === 1) { path = rootPath; root = process.cwd(); } if (root == null) { throw new TypeError('argument rootPath is required'); } if (typeof root !== 'string') { throw new TypeError('argument rootPath must be a string'); } if (path == null) { throw new TypeError('argument relativePath is required'); } if (typeof path !== 'string') { throw new TypeError('argument relativePath must be a string'); } // 包含NULL字节是恶意的 if (path.indexOf('\0') !== -1) { throw createError(400, 'Malicious Path'); } // 路径绝不能是绝对路径 if (pathIsAbsolute.posix(path) || pathIsAbsolute.win32(path)) { throw createError(400, 'Malicious Path'); } // 路径超出根目录 if (UP_PATH_REGEXP.test(normalize('.' + sep + path))) { throw createError(403); } // 拼接相对路径 return normalize(join(resolve(root), path)); } export default resolvePath;