path-to-regexp#match TypeScript Examples
The following examples show how to use
path-to-regexp#match.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: mock.ts From mockiavelli with MIT License | 6 votes |
private parseMatcher(matcher: RequestMatcher) {
// TODO find a better alternative for url.parse
const { protocol, host, pathname, query } = parse(matcher.url, true);
const hasHostname = protocol && host;
return {
method: matcher.method,
hostname: hasHostname ? `${protocol}//${host}` : undefined,
query: matcher.query ? matcher.query : query,
path: pathname ?? '',
pathMatch: match<PathParameters>(pathname ?? ''),
body: matcher.body,
};
}
Example #2
Source File: validatePath.ts From openapi-mock-express-middleware with MIT License | 6 votes |
validatePath = (
req: express.Request,
res: express.Response,
next: express.NextFunction
): void | express.Response => {
if (!res.locals.operation || !(res.locals.operation instanceof Operation)) {
return next();
}
const schemas: ParamsSchemas = res.locals.operation.getParamsSchemas();
const matchPath = match(res.locals.operation.pathPattern);
const matchObject = matchPath(req.path);
if ((matchObject && matchObject.params) || schemas.path) {
const isPathValid = validator.validate(schemas.path, (matchObject && matchObject.params) || {});
if (!isPathValid) {
return res.status(400).json({
message: 'Bad request. Invalid path params.',
errors: validator.errors,
});
}
}
return next();
}
Example #3
Source File: routes.ts From the-fake-backend with ISC License | 6 votes |
export function findRouteByUrl(routes: Route[], url: string): Route {
const route = routes.find(({ path }) => {
const routeMatch = match(path);
return routeMatch(url);
});
if (route) {
return route;
}
throw new Error(`Route with url "${url}" not found`);
}
Example #4
Source File: server.ts From mui-toolpad with MIT License | 5 votes |
/**
* Handler for new connections
* @param api The api for the handler object
* @param req The request object
* @param res The response object
*/
async function handler(
api: CreateHandlerApi<GoogleSheetsConnectionParams>,
req: NextApiRequest,
res: NextApiResponse,
): Promise<NextApiResponse | void> {
const client = createOAuthClient();
try {
const pathname = `/${asArray(req.query.path)
.map((segment) => encodeURIComponent(segment))
.join('/')}`;
const matchAuthLogin = match('/auth/login', { decode: decodeURIComponent });
const matchAuthCallback = match('/auth/callback', { decode: decodeURIComponent });
const [state] = asArray(req.query.state);
const { connectionId, appId } = JSON.parse(decodeURIComponent(state));
// Check if connection with connectionId exists, if so: merge
const savedConnection = await api.getConnectionParams(appId, connectionId);
if (savedConnection) {
client.setCredentials(savedConnection);
}
if (matchAuthLogin(pathname)) {
return res.redirect(
client.generateAuthUrl({
access_type: 'offline',
scope: [
'https://www.googleapis.com/auth/spreadsheets.readonly',
'https://www.googleapis.com/auth/drive.readonly',
],
state,
include_granted_scopes: true,
prompt: 'consent',
}),
);
}
if (matchAuthCallback(pathname)) {
const [oAuthError] = asArray(req.query.error);
if (oAuthError) {
throw new Error(oAuthError);
}
const [code] = asArray(req.query.code);
const { tokens, res: getTokenResponse } = await client.getToken(code);
if (!tokens) {
throw new Error(`${getTokenResponse?.status}: ${getTokenResponse?.statusText}`);
}
if (tokens) {
client.setCredentials(tokens);
await api.setConnectionParams(appId, connectionId, client.credentials);
}
return res.redirect(
`/_toolpad/app/${encodeURIComponent(appId)}/editor/connections/${encodeURIComponent(
connectionId,
)}`,
);
}
return res.status(404).send('No handler exists for given path');
} catch (e) {
if (e instanceof Error) {
console.error(e.message);
return res.status(500).send(e.message);
}
return res.status(500).send(e);
}
}
Example #5
Source File: utils.ts From next-crud with MIT License | 5 votes |
getRouteType = ({
method,
url,
resourceName,
}: GetRouteTypeParams): GetRouteType | null => {
// Exclude the query params from the path
const realPath = url.split('?')[0]
if (!realPath.includes(`/${resourceName}`)) {
throw new Error(
`invalid resource name '${resourceName}' for route '${realPath}'`
)
}
const entityMatcher = match<TPathMatch>(
[`/(.*)/${resourceName}`, `/(.*)/${resourceName}/:id`],
{ decode: decodeURIComponent }
)
const simpleMatcher = match(`/(.*)/${resourceName}`, {
decode: decodeURIComponent,
})
switch (method) {
case 'GET': {
const pathMatch = entityMatcher(realPath)
// If we got a /something after the resource name, we are reading 1 entity
if (pathMatch && pathMatch.params.id) {
return {
routeType: RouteType.READ_ONE,
resourceId: pathMatch.params.id,
}
}
return {
routeType: RouteType.READ_ALL,
}
}
case 'POST': {
const pathMatch = simpleMatcher(realPath)
if (pathMatch) {
return {
routeType: RouteType.CREATE,
}
}
return {
routeType: null,
}
}
case 'PUT':
case 'PATCH': {
const pathMatch = entityMatcher(realPath)
if (pathMatch && pathMatch.params.id) {
return {
routeType: RouteType.UPDATE,
resourceId: pathMatch.params.id,
}
}
return {
routeType: null,
}
}
case 'DELETE': {
const pathMatch = entityMatcher(realPath)
if (pathMatch && pathMatch.params.id) {
return {
routeType: RouteType.DELETE,
resourceId: pathMatch.params.id,
}
}
return {
routeType: null,
}
}
default: {
return {
routeType: null,
}
}
}
}
Example #6
Source File: onCreatePage.ts From gatsby-plugin-react-i18next with MIT License | 4 votes |
onCreatePage = async (
{page, actions}: CreatePageArgs<PageContext>,
pluginOptions: PluginOptions
) => {
//Exit if the page has already been processed.
if (typeof page.context.i18n === 'object') {
return;
}
const {createPage, deletePage} = actions;
const {
defaultLanguage = 'en',
generateDefaultLanguagePage = false,
languages = ['en'],
pages = []
} = pluginOptions;
type GeneratePageParams = {
language: string;
path?: string;
originalPath?: string;
routed?: boolean;
pageOptions?: PageOptions;
};
const generatePage = async ({
language,
path = page.path,
originalPath = page.path,
routed = false,
pageOptions
}: GeneratePageParams): Promise<Page<PageContext>> => {
return {
...page,
path,
context: {
...page.context,
language,
i18n: {
language,
languages: pageOptions?.languages || languages,
defaultLanguage,
generateDefaultLanguagePage,
routed,
originalPath,
path
}
}
};
};
const pageOptions = pages.find((opt) => match(opt.matchPath)(page.path));
let newPage;
let alternativeLanguages = generateDefaultLanguagePage
? languages
: languages.filter((lng) => lng !== defaultLanguage);
if (pageOptions?.excludeLanguages) {
alternativeLanguages = alternativeLanguages.filter(
(lng) => !pageOptions?.excludeLanguages?.includes(lng)
);
}
if (pageOptions?.languages) {
alternativeLanguages = generateDefaultLanguagePage
? pageOptions.languages
: pageOptions.languages.filter((lng) => lng !== defaultLanguage);
}
if (pageOptions?.getLanguageFromPath) {
const result = match<{lang: string}>(pageOptions.matchPath)(page.path);
if (!result) return;
const language = languages.find((lng) => lng === result.params.lang) || defaultLanguage;
const originalPath = page.path.replace(`/${language}`, '');
const routed = Boolean(result.params.lang);
newPage = await generatePage({language, originalPath, routed, pageOptions});
if (routed || !pageOptions.excludeLanguages) {
alternativeLanguages = [];
}
} else {
newPage = await generatePage({language: defaultLanguage, pageOptions});
}
try {
deletePage(page);
} catch {}
createPage(newPage);
await BP.map(alternativeLanguages, async (lng) => {
const localePage = await generatePage({
language: lng,
path: `${lng}${page.path}`,
routed: true
});
const regexp = new RegExp('/404/?$');
if (regexp.test(localePage.path)) {
localePage.matchPath = `/${lng}/*`;
}
if (localePage.matchPath !== undefined) {
localePage.matchPath = `/${lng}${localePage.matchPath}`;
}
createPage(localePage);
});
}
Example #7
Source File: common.ts From cli with MIT License | 4 votes |
export async function parseInvokeOptionsByOriginUrl(
options: DevPackOptions,
req,
getFuncList
): Promise<{
invokeOptions: Partial<InvokeOptions>;
invokeFun?: any;
}> {
const ignorePattern = options.ignorePattern;
const currentUrl = getPath(req);
const currentMethod = req.method.toLowerCase();
if (ignorePattern) {
if (typeof ignorePattern === 'function') {
if (ignorePattern(req)) {
return {
invokeOptions: {},
};
}
} else if (ignorePattern.length) {
for (const pattern of ignorePattern as string[]) {
if (new RegExp(pattern).test(currentUrl)) {
return {
invokeOptions: {},
};
}
}
}
}
const invokeOptions: Partial<InvokeOptions> = {};
invokeOptions.functionDir = options.functionDir;
invokeOptions.sourceDir = options.sourceDir;
invokeOptions.verbose = options.verbose;
const { functionList, invoke } = await getFuncList({
getFunctionList: true,
functionDir: options.functionDir,
sourceDir: options.sourceDir,
verbose: options.verbose,
});
const invokeHTTPData: Partial<{
headers: any;
body: string;
method: string;
path: string;
url: string;
query: any;
base64Encoded: boolean;
pathParameters: {
[name: string]: string;
};
}> = {};
// 获取路由
let urlMatchList = [];
Object.keys(functionList).forEach(functionName => {
const functionItem = functionList[functionName] || {};
const httpEvents = (functionItem.events || []).filter((eventItem: any) => {
return eventItem.http || eventItem.apigw;
});
for (const event of httpEvents) {
const eventItem = event?.http || event?.apigw;
if (eventItem) {
const router = eventItem.path?.replace(/\/\*$/, '/(.*)?') || '/(.*)?';
urlMatchList.push({
functionName,
functionHandler: functionItem.handler,
router,
originRouter: eventItem.path || '/*',
pureRouter: eventItem.path?.replace(/\/\*$/, '/') || '/',
level: router.split('/').length - 1,
paramsMatchLevel: router.indexOf('/:') !== -1 ? 1 : 0,
method: (eventItem.method ? [].concat(eventItem.method) : []).map(
method => {
return method.toLowerCase();
}
),
});
}
}
});
// 1. 绝对路径规则优先级最高如 /ab/cb/e
// 2. 星号只能出现最后且必须在/后面,如 /ab/cb/**
// 3. 如果绝对路径和通配都能匹配一个路径时,绝对规则优先级高
// 4. 有多个通配能匹配一个路径时,最长的规则匹配,如 /ab/** 和 /ab/cd/** 在匹配 /ab/cd/f 时命中 /ab/cd/**
// 5. 如果 / 与 /* 都能匹配 / ,但 / 的优先级高于 /*
urlMatchList = urlMatchList.sort((handlerA, handlerB) => {
if (handlerA.level === handlerB.level) {
if (handlerA.pureRouter === handlerB.pureRouter) {
return handlerA.router.length - handlerB.router.length;
}
if (handlerA.paramsMatchLevel === handlerB.paramsMatchLevel) {
return handlerB.pureRouter.length - handlerA.pureRouter.length;
}
return handlerA.paramsMatchLevel - handlerB.paramsMatchLevel;
}
return handlerB.level - handlerA.level;
});
let matchRes;
const functionItem = urlMatchList.find(item => {
matchRes = match(item.router)(currentUrl);
if (matchRes) {
if (item.method.length && item.method.indexOf(currentMethod) === -1) {
return false;
}
// 如果不在白名单内,并且是需要被忽略的函数,则跳过函数处理
if (
!ignoreWildcardFunctionsWhiteList.includes(currentUrl) &&
options.ignoreWildcardFunctions?.includes(item.functionName)
) {
// 中后台 webpack 的特殊处理,忽略特定函数的通配逻辑
return currentUrl.indexOf(item.originRouter) !== -1;
}
return true;
}
});
if (functionItem?.functionName) {
// 匹配到了函数
invokeOptions.functionName = functionItem.functionName;
invokeOptions.functionHandler = functionItem.functionHandler;
// 构造参数
invokeHTTPData.headers = req.headers;
if (req.body) {
const contentType = invokeHTTPData.headers['content-type'] || '';
if (contentType.startsWith('application/x-www-form-urlencoded')) {
invokeHTTPData.body = qs.stringify(req.body);
} else if (contentType.startsWith('multipart/form-data')) {
if (req.pipe) {
req.body = await getRawBody(req);
}
invokeHTTPData.body = req.body;
} else if (contentType.startsWith('application/json')) {
invokeHTTPData.body = JSON.stringify(req.body);
} else {
invokeHTTPData.body = `${req.body}`;
}
} else {
invokeHTTPData.body = undefined;
}
invokeHTTPData.method = req.method;
invokeHTTPData.pathParameters = matchRes.params || {};
invokeHTTPData.path = currentUrl;
invokeHTTPData.url = req.url;
invokeHTTPData.query = getQuery(req);
invokeHTTPData.base64Encoded = false;
invokeOptions.data = [invokeHTTPData];
}
return {
invokeOptions,
invokeFun: invoke,
};
}
Example #8
Source File: index.test.ts From cli with MIT License | 4 votes |
describe('/test/index.test.ts', () => {
describe('test url match', () => {
it('test micromatch', () => {
assert.equal(isMatch('/server/user/info', '/server/user/info'), true);
assert.equal(isMatch('/server/user/info', '/server/user/info/1'), false);
assert.equal(isMatch('/server/user/info', '/server/user/info/**'), true);
assert.equal(isMatch('/server/user/info', '/server/user/**'), true);
assert.equal(isMatch('/bbbbbb/ccccc', '/**'), true);
assert.equal(isMatch('/api/abc', '/api/**'), true);
assert.equal(isMatch('/api/a/b/c/d', '/api/a/b/c'), false);
});
it('test path-to-regexp', () => {
assert.equal(!!match('/server/user/info')('/server/user/info'), true);
assert.equal(!!match('/server/user/info/1')('/server/user/info'), false);
assert.equal(
!!match('/server/user/info/(.*)?')('/server/user/info'),
true
);
assert.equal(!!match('/server/user/(.*)?')('/server/user/info'), true);
assert.equal(!!match('/(.*)?')('/bbbbbb/ccccc'), true);
assert.equal(!!match('/api/(.*)?')('/api/abc'), true);
assert.equal(!!match('/api/a/b/c')('/api/a/b/c/d'), false);
});
it('test minimatch', () => {
assert.equal(minimatch('/server/user/info', '/server/user/info'), true);
assert.equal(
minimatch('/server/user/info', '/server/user/info/1'),
false
);
// assert.equal(minimatch('/server/user/info', '/server/user/info/**'), true);
assert.equal(minimatch('/server/user/info', '/server/user/**'), true);
assert.equal(minimatch('/bbbbbb/ccccc', '/**'), true);
assert.equal(minimatch('/api/abc', '/api/**'), true);
assert.equal(minimatch('/api/a/b/c/d', '/api/a/b/c'), false);
});
it('test picomatch', () => {
assert.equal(
picomatch.isMatch('/server/user/info', '/server/user/info'),
true
);
assert.equal(
picomatch.isMatch('/server/user/info', '/server/user/info/1'),
false
);
assert.equal(
picomatch.isMatch('/server/user/info', '/server/user/info/**'),
true
);
assert.equal(
picomatch.isMatch('/server/user/info', '/server/user/**'),
true
);
assert.equal(picomatch.isMatch('/bbbbbb/ccccc', '/**'), true);
assert.equal(picomatch.isMatch('/api/abc', '/api/**'), true);
assert.equal(picomatch.isMatch('/api/a/b/c/d', '/api/a/b/c'), false);
});
});
describe('test express', () => {
it('test /server/user/info', done => {
createExpressSuit({
functionDir: join(__dirname, './fixtures/ice-demo-repo'),
sourceDir: 'src/apis',
})
.post('/server/user/info')
.query({
action: 'doTest',
})
.send({ name: 'zhangting' })
.expect('Content-type', 'text/html; charset=utf-8')
.expect(/zhangting,hello http world,doTest/)
.expect('x-schema', 'bbb')
.expect(200, done);
});
it('test second url /server/user/info2', done => {
createExpressSuit({
functionDir: join(__dirname, './fixtures/ice-demo-repo'),
sourceDir: 'src/apis',
})
.post('/server/user/info2')
.query({
action: 'doTest',
})
.send({ name: 'zhangting' })
.expect('Content-type', 'text/html; charset=utf-8')
.expect(/zhangting,hello http world,doTest/)
.expect('x-schema', 'bbb')
.expect(200, done);
});
it('test /* router', done => {
createExpressSuit({
functionDir: join(__dirname, './fixtures/ice-demo-repo'),
sourceDir: 'src/apis',
})
.post('/bbbbbb/ccccc')
.query({
action: 'doTest',
})
.expect(/test2/)
.expect(200, done);
});
it('test /api/* router', done => {
createExpressSuit({
functionDir: join(__dirname, './fixtures/ice-demo-repo'),
sourceDir: 'src/apis',
})
.post('/api/abc')
.query({
action: 'doTest',
})
.expect(/test3/)
.expect(200, done);
});
it('test /api/a/b/c router', done => {
createExpressSuit({
functionDir: join(__dirname, './fixtures/ice-demo-repo'),
sourceDir: 'src/apis',
})
.post('/api/a/b/c')
.query({
action: 'doTest',
})
.expect(/test4/)
.expect(200, done);
});
it('test /api/a/b/c/d router must match /api/* not /api/a/b/c', done => {
createExpressSuit({
functionDir: join(__dirname, './fixtures/ice-demo-repo'),
sourceDir: 'src/apis',
})
.post('/api/a/b/c/d')
.expect(/test3/)
.expect(200, done);
});
it('test /api/ router', done => {
createExpressSuit({
functionDir: join(__dirname, './fixtures/ice-demo-repo'),
sourceDir: 'src/apis',
})
.post('/api/')
.query({
action: 'doTest',
})
.expect(/test6/)
.expect(200, done);
});
});
it('should invoke by http api and koa', done => {
createKoaSuit({
functionDir: join(__dirname, './fixtures/ice-demo-repo'),
sourceDir: 'src/apis',
})
.post('/server/user/info')
.query({
action: 'doTest',
})
.send({ name: 'zhangting' })
.expect('Content-type', 'text/html; charset=utf-8')
.expect(/zhangting,hello http world,doTest/)
.expect('x-schema', 'bbb')
.expect(200, done);
});
it('should invoke second url by http api and koa', done => {
createKoaSuit({
functionDir: join(__dirname, './fixtures/ice-demo-repo'),
sourceDir: 'src/apis',
})
.post('/server/user/info2')
.query({
action: 'doTest',
})
.send({ name: 'zhangting' })
.expect('Content-type', 'text/html; charset=utf-8')
.expect(/zhangting,hello http world,doTest/)
.expect('x-schema', 'bbb')
.expect(200, done);
});
it('should invoke *.json', done => {
createKoaSuit({
functionDir: join(__dirname, './fixtures/ice-demo-repo'),
sourceDir: 'src/apis',
})
.post('/json/test.json')
.query({
action: 'doTest',
})
.send({ name: 'zhangting' })
.expect('Content-type', 'text/html; charset=utf-8')
.expect(/zhangting,hello http world,doTest/)
.expect('x-schema', 'bbb')
.expect(200, done);
});
it('should get param from path', done => {
createKoaSuit({
functionDir: join(__dirname, './fixtures/ice-demo-repo'),
sourceDir: 'src/apis',
})
.get('/param/xijian/info')
.expect(/xijian,hello http world/)
.expect(200, done);
});
describe('test koa ignore pattern', () => {
it('should test ignore pattern', done => {
createKoaSuit({
functionDir: join(__dirname, './fixtures/ice-demo-repo'),
sourceDir: 'src/apis',
ignorePattern: ['.do'],
})
.post('/ignore.do')
.send({ name: 'zhangting' })
.expect(404, done);
});
it('should test ignore pattern by function', done => {
createKoaSuit({
functionDir: join(__dirname, './fixtures/ice-demo-repo'),
sourceDir: 'src/apis',
ignorePattern: req => {
return /\.do/.test(req.url);
},
})
.post('/ignore.do')
.send({ name: 'zhangting' })
.expect(404, done);
});
it('should support ignore wildcard function', done => {
createKoaSuit({
functionDir: join(__dirname, './fixtures/ice-demo-repo'),
sourceDir: 'src/apis',
ignoreWildcardFunctions: ['test2'],
})
.post('/p')
.send({ name: 'zhangting' })
.expect(404, done);
});
});
describe('test express ignore pattern', () => {
it('should test ignore pattern', done => {
createExpressSuit({
functionDir: join(__dirname, './fixtures/ice-demo-repo'),
sourceDir: 'src/apis',
ignorePattern: ['.do'],
})
.post('/ignore.do')
.send({ name: 'zhangting' })
.expect(404, done);
});
it('should test ignore pattern by function', done => {
createExpressSuit({
functionDir: join(__dirname, './fixtures/ice-demo-repo'),
sourceDir: 'src/apis',
ignorePattern: req => {
return /\.do/.test(req.url);
},
})
.post('/ignore.do')
.send({ name: 'zhangting' })
.expect(404, done);
});
it('should support ignore wildcard function', done => {
createExpressSuit({
functionDir: join(__dirname, './fixtures/ice-demo-repo'),
sourceDir: 'src/apis',
ignoreWildcardFunctions: ['test2'],
})
.post('/p')
.send({ name: 'zhangting' })
.expect(404, done);
});
});
});