mirror of
https://github.com/verdaccio/verdaccio.git
synced 2024-12-16 21:56:25 -05:00
fix(middleware): encoding of scoped package name (#4874)
* fix(middleware): encoding of scope package name * Change order * Test description * debug * Add to tests
This commit is contained in:
parent
7902331894
commit
5bb81ebf91
3 changed files with 98 additions and 0 deletions
5
.changeset/nine-countries-remember.md
Normal file
5
.changeset/nine-countries-remember.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'@verdaccio/middleware': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix(middleware): encoding of scope package name
|
|
@ -1,5 +1,9 @@
|
||||||
|
import buildDebug from 'debug';
|
||||||
|
|
||||||
import { $NextFunctionVer, $RequestExtend, $ResponseExtend } from '../types';
|
import { $NextFunctionVer, $RequestExtend, $ResponseExtend } from '../types';
|
||||||
|
|
||||||
|
const debug = buildDebug('verdaccio:middleware:encode');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encode / in a scoped package name to be matched as a single parameter in routes
|
* Encode / in a scoped package name to be matched as a single parameter in routes
|
||||||
* @param req
|
* @param req
|
||||||
|
@ -11,9 +15,16 @@ export function encodeScopePackage(
|
||||||
res: $ResponseExtend,
|
res: $ResponseExtend,
|
||||||
next: $NextFunctionVer
|
next: $NextFunctionVer
|
||||||
): void {
|
): void {
|
||||||
|
const original = req.url;
|
||||||
|
// If the @ sign is encoded, we need to decode it first
|
||||||
|
// e.g.: /%40org/pkg/1.2.3 -> /@org/pkg/1.2.3
|
||||||
|
if (req.url.indexOf('%40') !== -1) {
|
||||||
|
req.url = req.url.replace(/^\/%40/, '/@');
|
||||||
|
}
|
||||||
if (req.url.indexOf('@') !== -1) {
|
if (req.url.indexOf('@') !== -1) {
|
||||||
// e.g.: /@org/pkg/1.2.3 -> /@org%2Fpkg/1.2.3, /@org%2Fpkg/1.2.3 -> /@org%2Fpkg/1.2.3
|
// e.g.: /@org/pkg/1.2.3 -> /@org%2Fpkg/1.2.3, /@org%2Fpkg/1.2.3 -> /@org%2Fpkg/1.2.3
|
||||||
req.url = req.url.replace(/^(\/@[^\/%]+)\/(?!$)/, '$1%2F');
|
req.url = req.url.replace(/^(\/@[^\/%]+)\/(?!$)/, '$1%2F');
|
||||||
}
|
}
|
||||||
|
debug('encodeScopePackage: %o -> %o', original, req.url);
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,3 +20,85 @@ test('encode is json', async () => {
|
||||||
expect(res.body).toEqual({ id: '@scope/foo' });
|
expect(res.body).toEqual({ id: '@scope/foo' });
|
||||||
expect(res.status).toEqual(HTTP_STATUS.OK);
|
expect(res.status).toEqual(HTTP_STATUS.OK);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('packages with version/scope', async () => {
|
||||||
|
const app = getApp([]);
|
||||||
|
// @ts-ignore
|
||||||
|
app.use(encodeScopePackage);
|
||||||
|
// @ts-ignore
|
||||||
|
app.get('/:package/:version?', (req, res) => {
|
||||||
|
const { package: pkg, version } = req.params;
|
||||||
|
res.status(HTTP_STATUS.OK).json({ package: pkg, version });
|
||||||
|
});
|
||||||
|
|
||||||
|
const res = await request(app).get('/foo');
|
||||||
|
expect(res.body).toEqual({ package: 'foo' });
|
||||||
|
expect(res.status).toEqual(HTTP_STATUS.OK);
|
||||||
|
|
||||||
|
const res2 = await request(app).get('/foo/1.0.0');
|
||||||
|
expect(res2.body).toEqual({ package: 'foo', version: '1.0.0' });
|
||||||
|
expect(res2.status).toEqual(HTTP_STATUS.OK);
|
||||||
|
|
||||||
|
const res3 = await request(app).get('/@scope/foo');
|
||||||
|
expect(res3.body).toEqual({ package: '@scope/foo' });
|
||||||
|
expect(res3.status).toEqual(HTTP_STATUS.OK);
|
||||||
|
|
||||||
|
const res4 = await request(app).get('/@scope/foo/1.0.0');
|
||||||
|
expect(res4.body).toEqual({ package: '@scope/foo', version: '1.0.0' });
|
||||||
|
expect(res4.status).toEqual(HTTP_STATUS.OK);
|
||||||
|
|
||||||
|
const res5 = await request(app).get('/@scope%2ffoo');
|
||||||
|
expect(res5.body).toEqual({ package: '@scope/foo' });
|
||||||
|
expect(res5.status).toEqual(HTTP_STATUS.OK);
|
||||||
|
|
||||||
|
const res6 = await request(app).get('/@scope%2ffoo/1.0.0');
|
||||||
|
expect(res6.body).toEqual({ package: '@scope/foo', version: '1.0.0' });
|
||||||
|
expect(res6.status).toEqual(HTTP_STATUS.OK);
|
||||||
|
|
||||||
|
const res7 = await request(app).get('/%40scope%2ffoo');
|
||||||
|
expect(res7.body).toEqual({ package: '@scope/foo' });
|
||||||
|
expect(res7.status).toEqual(HTTP_STATUS.OK);
|
||||||
|
|
||||||
|
const res8 = await request(app).get('/%40scope%2ffoo/1.0.0');
|
||||||
|
expect(res8.body).toEqual({ package: '@scope/foo', version: '1.0.0' });
|
||||||
|
expect(res8.status).toEqual(HTTP_STATUS.OK);
|
||||||
|
|
||||||
|
const res9 = await request(app).get('/%40scope/foo');
|
||||||
|
expect(res9.body).toEqual({ package: '@scope/foo' });
|
||||||
|
expect(res9.status).toEqual(HTTP_STATUS.OK);
|
||||||
|
|
||||||
|
const res10 = await request(app).get('/%40scope/foo/1.0.0');
|
||||||
|
expect(res10.body).toEqual({ package: '@scope/foo', version: '1.0.0' });
|
||||||
|
expect(res10.status).toEqual(HTTP_STATUS.OK);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('tarballs with and without scope', async () => {
|
||||||
|
const app = getApp([]);
|
||||||
|
// @ts-ignore
|
||||||
|
app.use(encodeScopePackage);
|
||||||
|
// @ts-ignore
|
||||||
|
app.get('/:package/-/:filename', (req, res) => {
|
||||||
|
const { package: pkg, filename } = req.params;
|
||||||
|
res.status(HTTP_STATUS.OK).json({ package: pkg, filename });
|
||||||
|
});
|
||||||
|
|
||||||
|
const res = await request(app).get('/foo/-/foo-1.2.3.tgz');
|
||||||
|
expect(res.body).toEqual({ package: 'foo', filename: 'foo-1.2.3.tgz' });
|
||||||
|
expect(res.status).toEqual(HTTP_STATUS.OK);
|
||||||
|
|
||||||
|
const res2 = await request(app).get('/@scope/foo/-/foo-1.2.3.tgz');
|
||||||
|
expect(res2.body).toEqual({ package: '@scope/foo', filename: 'foo-1.2.3.tgz' });
|
||||||
|
expect(res2.status).toEqual(HTTP_STATUS.OK);
|
||||||
|
|
||||||
|
const res3 = await request(app).get('/@scope%2ffoo/-/foo-1.2.3.tgz');
|
||||||
|
expect(res3.body).toEqual({ package: '@scope/foo', filename: 'foo-1.2.3.tgz' });
|
||||||
|
expect(res3.status).toEqual(HTTP_STATUS.OK);
|
||||||
|
|
||||||
|
const res4 = await request(app).get('/%40scope%2ffoo/-/foo-1.2.3.tgz');
|
||||||
|
expect(res4.body).toEqual({ package: '@scope/foo', filename: 'foo-1.2.3.tgz' });
|
||||||
|
expect(res4.status).toEqual(HTTP_STATUS.OK);
|
||||||
|
|
||||||
|
const res5 = await request(app).get('/%40scope/foo/-/foo-1.2.3.tgz');
|
||||||
|
expect(res5.body).toEqual({ package: '@scope/foo', filename: 'foo-1.2.3.tgz' });
|
||||||
|
expect(res5.status).toEqual(HTTP_STATUS.OK);
|
||||||
|
});
|
||||||
|
|
Loading…
Reference in a new issue