From 7158e66c9f09af76144beff28aa1899510080f4b Mon Sep 17 00:00:00 2001 From: ZhengJin Date: Sun, 3 Nov 2024 20:35:45 +0800 Subject: [PATCH 1/2] feat: compatible verdaccio path style (#723) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 兼容Verdaccio下载地址风格,镜像库从Verdaccio切换至cnpmcore后无需大面积调整lock文件 ## Summary by CodeRabbit - **New Features** - Introduced a comprehensive test suite for the download functionality, ensuring robust behavior for various package retrieval scenarios. - Enhanced validation for CORS requests and CDN redirection during package downloads. - Added new test cases for downloading version tarballs with scoped package handling. - **Bug Fixes** - Improved error handling for non-existent packages and versions, providing clearer error messages. - Ensured proper handling of deprecated download paths and scoped/non-scoped package names. --- .../package/DownloadPackageVersionTar.ts | 20 ++++++++ ...ownloadPackageVersionTarController.test.ts | 51 ++++++++++++++++++- 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/app/port/controller/package/DownloadPackageVersionTar.ts b/app/port/controller/package/DownloadPackageVersionTar.ts index 5395e2e4..03ddb15c 100644 --- a/app/port/controller/package/DownloadPackageVersionTar.ts +++ b/app/port/controller/package/DownloadPackageVersionTar.ts @@ -133,4 +133,24 @@ export class DownloadPackageVersionTarController extends AbstractController { }); return res; } + + // Compatible Verdaccio path style + + @HTTPMethod({ + // GET /:fullname/-/:scope/:filenameWithVersion.tgz + path: `/:fullname(${FULLNAME_REG_STRING})/-/:scope/:filenameWithVersion.tgz`, + method: HTTPMethodEnum.OPTIONS, + }) + async downloadVerdaccioPathStyleorOptions(@Context() ctx: EggContext) { + return this.downloadForOptions(ctx); + } + + @HTTPMethod({ + // GET /:fullname/-/:scope/:filenameWithVersion.tgz + path: `/:fullname(${FULLNAME_REG_STRING})/-/:scope/:filenameWithVersion.tgz`, + method: HTTPMethodEnum.GET, + }) + async downloadVerdaccioPathStyle(@Context() ctx: EggContext, @HTTPParam() fullname: string, @HTTPParam() filenameWithVersion: string) { + return this.download(ctx, fullname, filenameWithVersion); + } } diff --git a/test/port/controller/package/DownloadPackageVersionTarController.test.ts b/test/port/controller/package/DownloadPackageVersionTarController.test.ts index 4b0e182d..1fd7abb7 100644 --- a/test/port/controller/package/DownloadPackageVersionTarController.test.ts +++ b/test/port/controller/package/DownloadPackageVersionTarController.test.ts @@ -13,8 +13,9 @@ describe('test/port/controller/package/DownloadPackageVersionTarController.test. nfsClientAdapter = await app.getEggObject(NFSClientAdapter); }); - const scopedName = '@cnpm/testmodule-download-version-tar'; + const scope = '@cnpm'; const name = 'testmodule-download-version-tar'; + const scopedName = `${scope}/${name}`; beforeEach(async () => { mock(app.config.cnpmcore, 'allowPublishNonScopePackage', true); let pkg = await TestUtil.getFullPackage({ name, version: '1.0.0' }); @@ -367,4 +368,52 @@ describe('test/port/controller/package/DownloadPackageVersionTarController.test. assert(res.body.error === `[NOT_FOUND] "${name}-1.0.0.tgz" not found`); }); }); + + describe('[GET /:fullname/-/:scope/:name-:version.tgz] download()', () => { + it('should download a version tar redirect to mock cdn success', async () => { + mock(nfsClientAdapter, 'url', async (storeKey: string) => { + // console.log('call url: ', storeKey); + return `https://cdn.mock.com${storeKey}`; + }); + let res = await app.httpRequest() + .get(`/${name}/-/${scope}/${name}-1.0.0.tgz`); + assert(res.status === 302); + assert(res.headers.location === `https://cdn.mock.com/packages/${name}/1.0.0/${name}-1.0.0.tgz`); + res = await app.httpRequest() + .get(`/${scopedName}/-/${scope}/${name}-1.0.0.tgz`); + assert(res.status === 302); + assert(res.headers.location === `https://cdn.mock.com/packages/${scopedName}/1.0.0/${name}-1.0.0.tgz`); + }); + + it('should download a version tar with streaming success', async () => { + mock(nfsClientAdapter, 'url', 'not-function'); + const res = await app.httpRequest() + .get(`/${name}/-/${scope}/${name}-1.0.0.tgz`); + assert(res.status === 200); + assert(res.headers['content-type'] === 'application/octet-stream'); + assert(res.headers['content-disposition'] === `attachment; filename="${name}-1.0.0.tgz"`); + + await app.httpRequest() + .get(`/${scopedName}/-/${scope}/${name}-1.0.0.tgz`); + assert(res.status === 200); + assert(res.headers['content-type'] === 'application/octet-stream'); + assert(res.headers['content-disposition'] === `attachment; filename="${name}-1.0.0.tgz"`); + }); + + it('should mock getDownloadUrlOrStream return undefined', async () => { + mock(nfsClientAdapter, 'createDownloadStream', async () => { + return undefined; + }); + if (process.env.CNPMCORE_NFS_TYPE === 'oss') { + mock(nfsClientAdapter, 'url', async () => { + return undefined; + }); + } + const res = await app.httpRequest() + .get(`/${name}/-/${scope}/${name}-1.0.0.tgz`); + assert(res.status === 404); + assert(res.headers['content-type'] === 'application/json; charset=utf-8'); + assert(res.body.error === `[NOT_FOUND] "${name}-1.0.0.tgz" not found`); + }); + }); }); From 2edbec6008582e2aed57837588fe454d7e2787dc Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sun, 3 Nov 2024 12:37:16 +0000 Subject: [PATCH 2/2] Release 3.66.0 [skip ci] ## [3.66.0](https://github.com/cnpm/cnpmcore/compare/v3.65.0...v3.66.0) (2024-11-03) ### Features * compatible verdaccio path style ([#723](https://github.com/cnpm/cnpmcore/issues/723)) ([7158e66](https://github.com/cnpm/cnpmcore/commit/7158e66c9f09af76144beff28aa1899510080f4b)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9542bcb7..73f66a69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [3.66.0](https://github.com/cnpm/cnpmcore/compare/v3.65.0...v3.66.0) (2024-11-03) + + +### Features + +* compatible verdaccio path style ([#723](https://github.com/cnpm/cnpmcore/issues/723)) ([7158e66](https://github.com/cnpm/cnpmcore/commit/7158e66c9f09af76144beff28aa1899510080f4b)) + ## [3.65.0](https://github.com/cnpm/cnpmcore/compare/v3.64.0...v3.65.0) (2024-10-26) diff --git a/package.json b/package.json index d7d968f6..3468b114 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cnpmcore", - "version": "3.65.0", + "version": "3.66.0", "description": "npm core", "files": [ "dist/**/*"