2020-08-19 13:27:35 -05:00
|
|
|
import buildDebug from 'debug';
|
2021-10-29 10:33:05 -05:00
|
|
|
import { Router } from 'express';
|
2020-03-03 17:59:19 -05:00
|
|
|
|
2022-10-11 16:06:55 -05:00
|
|
|
import { Auth } from '@verdaccio/auth';
|
2022-09-06 01:25:17 -05:00
|
|
|
import { HEADERS, HEADER_TYPE, stringUtils } from '@verdaccio/core';
|
2023-02-05 15:00:32 -05:00
|
|
|
import { logger } from '@verdaccio/logger';
|
2021-10-29 10:33:05 -05:00
|
|
|
import { allow } from '@verdaccio/middleware';
|
2021-09-08 12:06:37 -05:00
|
|
|
import { Storage } from '@verdaccio/store';
|
2021-10-29 10:33:05 -05:00
|
|
|
|
|
|
|
import { $NextFunctionVer, $RequestExtend, $ResponseExtend } from '../types/custom';
|
2020-03-03 17:59:19 -05:00
|
|
|
|
2020-08-19 13:27:35 -05:00
|
|
|
const debug = buildDebug('verdaccio:api:package');
|
|
|
|
|
2022-10-11 16:06:55 -05:00
|
|
|
export default function (route: Router, auth: Auth, storage: Storage): void {
|
2023-02-05 15:00:32 -05:00
|
|
|
const can = allow(auth, {
|
|
|
|
beforeAll: (a, b) => logger.trace(a, b),
|
|
|
|
afterAll: (a, b) => logger.trace(a, b),
|
|
|
|
});
|
2021-01-16 04:40:43 -05:00
|
|
|
route.get(
|
|
|
|
'/:package/:version?',
|
|
|
|
can('access'),
|
2021-12-12 12:00:19 -05:00
|
|
|
async function (
|
|
|
|
req: $RequestExtend,
|
|
|
|
_res: $ResponseExtend,
|
|
|
|
next: $NextFunctionVer
|
|
|
|
): Promise<void> {
|
2021-01-16 04:40:43 -05:00
|
|
|
debug('init package by version');
|
|
|
|
const name = req.params.package;
|
2022-07-29 13:51:45 -05:00
|
|
|
let version = req.params.version;
|
|
|
|
const write = req.query.write === 'true';
|
2024-06-13 05:06:01 -05:00
|
|
|
const username = req?.remote_user?.name;
|
2022-09-06 01:25:17 -05:00
|
|
|
const abbreviated =
|
|
|
|
stringUtils.getByQualityPriorityValue(req.get('Accept')) === Storage.ABBREVIATED_HEADER;
|
2021-11-09 14:38:44 -05:00
|
|
|
const requestOptions = {
|
|
|
|
protocol: req.protocol,
|
|
|
|
headers: req.headers as any,
|
|
|
|
// FIXME: if we migrate to req.hostname, the port is not longer included.
|
|
|
|
host: req.host,
|
2022-07-29 13:51:45 -05:00
|
|
|
remoteAddress: req.socket.remoteAddress,
|
|
|
|
byPassCache: write,
|
2024-06-13 05:06:01 -05:00
|
|
|
username,
|
2021-11-09 14:38:44 -05:00
|
|
|
};
|
2020-03-03 17:59:19 -05:00
|
|
|
|
2021-12-12 12:00:19 -05:00
|
|
|
try {
|
2022-02-20 12:39:38 -05:00
|
|
|
const manifest = await storage.getPackageByOptions({
|
2021-12-12 12:00:19 -05:00
|
|
|
name,
|
|
|
|
uplinksLook: true,
|
2022-08-27 05:52:23 -05:00
|
|
|
abbreviated,
|
2022-07-29 13:51:45 -05:00
|
|
|
version,
|
2021-12-12 12:00:19 -05:00
|
|
|
requestOptions,
|
|
|
|
});
|
2022-09-06 01:25:17 -05:00
|
|
|
if (abbreviated) {
|
|
|
|
_res.setHeader(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_INSTALL_CHARSET);
|
|
|
|
} else {
|
|
|
|
_res.setHeader(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON);
|
|
|
|
}
|
|
|
|
|
2021-12-12 12:00:19 -05:00
|
|
|
next(manifest);
|
|
|
|
} catch (err) {
|
|
|
|
next(err);
|
2022-07-29 13:51:45 -05:00
|
|
|
}
|
2021-01-16 04:40:43 -05:00
|
|
|
}
|
|
|
|
);
|
2020-03-03 17:59:19 -05:00
|
|
|
|
2021-01-16 04:40:43 -05:00
|
|
|
route.get(
|
2023-01-31 11:09:38 -05:00
|
|
|
'/:package/-/:filename',
|
2021-01-16 04:40:43 -05:00
|
|
|
can('access'),
|
2022-07-29 13:51:45 -05:00
|
|
|
async function (req: $RequestExtend, res: $ResponseExtend, next): Promise<void> {
|
2023-01-31 11:09:38 -05:00
|
|
|
const { package: pkgName, filename } = req.params;
|
2022-07-29 13:51:45 -05:00
|
|
|
const abort = new AbortController();
|
|
|
|
try {
|
2024-03-10 11:58:39 -05:00
|
|
|
const stream = (await storage.getTarball(pkgName, filename, {
|
2022-07-29 13:51:45 -05:00
|
|
|
signal: abort.signal,
|
2022-09-02 13:40:12 -05:00
|
|
|
// TODO: review why this param
|
2022-07-29 13:51:45 -05:00
|
|
|
// enableRemote: true,
|
|
|
|
})) as any;
|
|
|
|
|
|
|
|
stream.on('content-length', (size) => {
|
|
|
|
res.header(HEADER_TYPE.CONTENT_LENGTH, size);
|
|
|
|
});
|
|
|
|
|
|
|
|
stream.once('error', (err) => {
|
|
|
|
res.locals.report_error(err);
|
|
|
|
next(err);
|
|
|
|
});
|
|
|
|
|
|
|
|
req.on('abort', () => {
|
|
|
|
debug('request aborted for %o', req.url);
|
|
|
|
abort.abort();
|
|
|
|
});
|
|
|
|
|
|
|
|
res.header(HEADERS.CONTENT_TYPE, HEADERS.OCTET_STREAM);
|
|
|
|
stream.pipe(res);
|
|
|
|
} catch (err: any) {
|
|
|
|
// console.log('catch API error request', err);
|
|
|
|
res.locals.report_error(err);
|
|
|
|
next(err);
|
|
|
|
}
|
2021-01-16 04:40:43 -05:00
|
|
|
}
|
|
|
|
);
|
2020-03-03 17:59:19 -05:00
|
|
|
}
|