mirror of
https://github.com/verdaccio/verdaccio.git
synced 2025-01-06 22:40:26 -05:00
fix: get header by quality priority value (#3359)
* fix: get header by quality priority value * chore: disable some workflows * chore: add more tests * chore: remove some duplicated testss * chore: return right content type haders
This commit is contained in:
parent
8ac917deb2
commit
cdb80aac20
5 changed files with 97 additions and 76 deletions
70
.github/workflows/e2e-gatsbyjs-cli-workflow.yml
vendored
70
.github/workflows/e2e-gatsbyjs-cli-workflow.yml
vendored
|
@ -42,73 +42,3 @@ jobs:
|
|||
gatsby new my-gatsby
|
||||
cd my-gatsby
|
||||
npm run build
|
||||
npm7:
|
||||
name: 'npm7:gatsby example'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3.0.2
|
||||
|
||||
- name: 'Use Node.js 14.x'
|
||||
uses: actions/setup-node@v2.5.1
|
||||
with:
|
||||
node-version: 14.x
|
||||
- name: 'install npm 7'
|
||||
run: npm i -g npm@latest-7
|
||||
- name: Install Dependencies
|
||||
run: yarn install
|
||||
- name: 'Run verdaccio in the background'
|
||||
run: |
|
||||
nohup yarn node ./scripts/run-verdaccio.js --config ./scripts/e2e-config.yaml &
|
||||
- name: 'Ping to verdaccio'
|
||||
run: |
|
||||
npm ping --registry http://localhost:4873
|
||||
- name: 'Running the integration test'
|
||||
run: |
|
||||
source scripts/e2e-setup-ci.sh
|
||||
echo "registry=http://localhost:4873
|
||||
loglevel="silent"
|
||||
fetch-retries=10
|
||||
fetch-retry-factor=2
|
||||
fetch-retry-mintimeout=10000
|
||||
fetch-retry-maxtimeout=80000" > ~/.npmrc
|
||||
npm config list
|
||||
npm i -g gatsby
|
||||
gatsby new my-gatsby
|
||||
cd my-gatsby
|
||||
npm run build
|
||||
npm8:
|
||||
name: 'npm8:gatsby example'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3.0.2
|
||||
|
||||
- name: 'Use Node.js 16.x'
|
||||
uses: actions/setup-node@v2.5.1
|
||||
with:
|
||||
node-version: 16.x
|
||||
- name: 'install npm 8'
|
||||
run: npm i -g npm@next-8
|
||||
- name: Install Dependencies
|
||||
run: yarn install
|
||||
- name: 'Run verdaccio in the background'
|
||||
run: |
|
||||
nohup yarn node ./scripts/run-verdaccio.js --config ./scripts/e2e-config.yaml &
|
||||
- name: 'Ping to verdaccio'
|
||||
run: |
|
||||
npm ping --registry http://localhost:4873
|
||||
- name: 'Running the integration test'
|
||||
run: |
|
||||
source scripts/e2e-setup-ci.sh
|
||||
echo "registry=http://localhost:4873
|
||||
loglevel="silent"
|
||||
fetch-retries=10
|
||||
fetch-retry-factor=2
|
||||
fetch-retry-mintimeout=10000
|
||||
fetch-retry-maxtimeout=80000" > ~/.npmrc
|
||||
npm config list
|
||||
npm i -g gatsby
|
||||
gatsby new my-gatsby
|
||||
cd my-gatsby
|
||||
npm run build
|
||||
|
|
|
@ -6,9 +6,9 @@ import { Config, Package } from '@verdaccio/types';
|
|||
import { $NextFunctionVer, $RequestExtend, $ResponseExtend, IAuth, IStorageHandler } from '../../../../types';
|
||||
import { API_ERROR, DIST_TAGS, HEADERS } from '../../../lib/constants';
|
||||
import { ErrorCode, convertDistRemoteToLocalTarballUrls, getVersion } from '../../../lib/utils';
|
||||
import { getByQualityPriorityValue } from '../../../utils/string';
|
||||
import { allow } from '../../middleware';
|
||||
|
||||
const ABBREVIATED_HEADER = 'application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*';
|
||||
const downloadStream = (packageName: string, filename: string, storage: any, req: $RequestExtend, res: $ResponseExtend): void => {
|
||||
const stream = storage.getTarball(packageName, filename);
|
||||
|
||||
|
@ -46,6 +46,7 @@ export default function (route: Router, auth: IAuth, storage: IStorageHandler, c
|
|||
const can = allow(auth);
|
||||
// TODO: anonymous user?
|
||||
route.get('/:package/:version?', can('access'), function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void {
|
||||
const abbreviated = getByQualityPriorityValue(req.get('Accept')) === 'application/vnd.npm.install-v1+json';
|
||||
const getPackageMetaCallback = function (err, metadata: Package): void {
|
||||
if (err) {
|
||||
return next(err);
|
||||
|
@ -54,11 +55,18 @@ export default function (route: Router, auth: IAuth, storage: IStorageHandler, c
|
|||
|
||||
let queryVersion = req.params.version;
|
||||
if (_.isNil(queryVersion)) {
|
||||
if (abbreviated) {
|
||||
res.setHeader(HEADERS.CONTENT_TYPE, 'application/vnd.npm.install-v1+json');
|
||||
} else {
|
||||
res.setHeader(HEADERS.CONTENT_TYPE, HEADERS.JSON);
|
||||
}
|
||||
|
||||
return next(metadata);
|
||||
}
|
||||
|
||||
let version = getVersion(metadata, queryVersion);
|
||||
if (_.isNil(version) === false) {
|
||||
res.setHeader(HEADERS.CONTENT_TYPE, HEADERS.JSON);
|
||||
return next(version);
|
||||
}
|
||||
|
||||
|
@ -67,13 +75,14 @@ export default function (route: Router, auth: IAuth, storage: IStorageHandler, c
|
|||
queryVersion = metadata[DIST_TAGS][queryVersion];
|
||||
version = getVersion(metadata, queryVersion);
|
||||
if (_.isNil(version) === false) {
|
||||
res.setHeader(HEADERS.CONTENT_TYPE, HEADERS.JSON);
|
||||
return next(version);
|
||||
}
|
||||
}
|
||||
}
|
||||
return next(ErrorCode.getNotFound(`${API_ERROR.VERSION_NOT_EXIST}: ${req.params.version}`));
|
||||
};
|
||||
const abbreviated = req.get('Accept') === ABBREVIATED_HEADER;
|
||||
|
||||
storage.getPackage({
|
||||
name: req.params.package,
|
||||
uplinksLook: true,
|
||||
|
|
|
@ -5,3 +5,40 @@ export function spliceURL(...args: string[]): string {
|
|||
.reduce((lastResult, current) => lastResult + current)
|
||||
.replace(/([^:])(\/)+(.)/g, `$1/$3`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Quality values, or q-values and q-factors, are used to describe the order
|
||||
* of priority of values in a comma-separated list.
|
||||
* It is a special syntax allowed in some HTTP headers and in HTML.
|
||||
* https://developer.mozilla.org/en-US/docs/Glossary/Quality_values
|
||||
* @param headerValue
|
||||
*/
|
||||
export function getByQualityPriorityValue(headerValue: string | undefined | null): string {
|
||||
if (typeof headerValue !== 'string') {
|
||||
return '';
|
||||
}
|
||||
|
||||
const split = headerValue.split(',');
|
||||
|
||||
if (split.length <= 1) {
|
||||
const qList = split[0].split(';');
|
||||
return qList[0];
|
||||
}
|
||||
|
||||
let [header] = split
|
||||
.reduce((acc, item: string) => {
|
||||
const qList = item.split(';');
|
||||
if (qList.length > 1) {
|
||||
const [accept, q] = qList;
|
||||
const [, query] = q.split('=');
|
||||
acc.push([accept.trim(), query ? query : 0]);
|
||||
} else {
|
||||
acc.push([qList[0], 0]);
|
||||
}
|
||||
return acc;
|
||||
}, [] as any)
|
||||
.sort(function (a, b) {
|
||||
return b[1] - a[1];
|
||||
});
|
||||
return header[0];
|
||||
}
|
||||
|
|
|
@ -339,12 +339,40 @@ describe('endpoint unit test', () => {
|
|||
});
|
||||
});
|
||||
|
||||
test('should fetch abbreviated jquery package from remote uplink', (done) => {
|
||||
test.each(['application/json; q=1.0, application/vnd.npm.install-v1+json; q=0.9, */*', 'application/json; q=1.0; q=1.0, */*', 'application/json'])(
|
||||
'should not fetch abbreviated jquery package from remote uplink with %s',
|
||||
(accept, done: any) => {
|
||||
request(app)
|
||||
.get('/jquery')
|
||||
.set('accept', accept)
|
||||
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
|
||||
.expect(HEADER_TYPE.CONTENT_ENCODING, HEADERS.GZIP)
|
||||
.expect(HEADERS.CONTENT_TYPE, HEADERS.JSON_CHARSET)
|
||||
.expect(HTTP_STATUS.OK)
|
||||
.end(function (err, res) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
const manifest = res.body;
|
||||
expect(manifest).toBeDefined();
|
||||
expect(manifest.name).toMatch(/jquery/);
|
||||
expect(manifest.readme).toBeDefined();
|
||||
done();
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
test.each([
|
||||
'application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*',
|
||||
'application/vnd.npm.install-v1+json; q=1.0, */*',
|
||||
'application/vnd.npm.install-v1+json',
|
||||
])('should fetch abbreviated jquery package from remote uplink with %s', (accept, done: any) => {
|
||||
request(app)
|
||||
.get('/jquery')
|
||||
.set('accept', 'application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*')
|
||||
.set('accept', accept)
|
||||
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
|
||||
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
|
||||
.expect(HEADER_TYPE.CONTENT_ENCODING, HEADERS.GZIP)
|
||||
.expect(HEADERS.CONTENT_TYPE, 'application/vnd.npm.install-v1+json; charset=utf-8')
|
||||
.expect(HTTP_STATUS.OK)
|
||||
.end(function (err, res) {
|
||||
if (err) {
|
||||
|
|
|
@ -21,7 +21,7 @@ import {
|
|||
validateName,
|
||||
validatePackage,
|
||||
} from '../../../../src/lib/utils';
|
||||
import { spliceURL } from '../../../../src/utils/string';
|
||||
import { getByQualityPriorityValue, spliceURL } from '../../../../src/utils/string';
|
||||
import { GENERIC_AVATAR, generateGravatarUrl } from '../../../../src/utils/user';
|
||||
import { readFile } from '../../../functional/lib/test.utils';
|
||||
|
||||
|
@ -369,6 +369,23 @@ describe('Utilities', () => {
|
|||
expect(isHTTPProtocol('/static/logo.png')).toBeFalsy();
|
||||
expect(isHTTPProtocol('F:\\static\\logo.png')).toBeFalsy();
|
||||
});
|
||||
|
||||
test('getByQualityPriorityValue', () => {
|
||||
expect(getByQualityPriorityValue('')).toEqual('');
|
||||
expect(getByQualityPriorityValue(null)).toEqual('');
|
||||
expect(getByQualityPriorityValue(undefined)).toEqual('');
|
||||
expect(getByQualityPriorityValue('something')).toEqual('something');
|
||||
expect(getByQualityPriorityValue('something,')).toEqual('something');
|
||||
expect(getByQualityPriorityValue('0,')).toEqual('0');
|
||||
expect(getByQualityPriorityValue('application/json')).toEqual('application/json');
|
||||
expect(getByQualityPriorityValue('application/json; q=1')).toEqual('application/json');
|
||||
expect(getByQualityPriorityValue('application/json; q=')).toEqual('application/json');
|
||||
expect(getByQualityPriorityValue('application/json;')).toEqual('application/json');
|
||||
expect(getByQualityPriorityValue('application/json; q=1.0, application/vnd.npm.install-v1+json; q=0.9, */*')).toEqual('application/json');
|
||||
expect(getByQualityPriorityValue('application/json; q=1.0, application/vnd.npm.install-v1+json; q=, */*')).toEqual('application/json');
|
||||
expect(getByQualityPriorityValue('application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.9, */*')).toEqual('application/vnd.npm.install-v1+json');
|
||||
expect(getByQualityPriorityValue('application/vnd.npm.install-v1+json; q=, application/json; q=0.9, */*')).toEqual('application/json');
|
||||
});
|
||||
});
|
||||
|
||||
describe('User utilities', () => {
|
||||
|
|
Loading…
Reference in a new issue