Remove addLeadingSlash util

This commit is contained in:
Michael Jackson 2019-07-10 21:59:23 -07:00
parent b2d8e28344
commit ab83549744
4 changed files with 35 additions and 48 deletions

View File

@ -1,7 +1,5 @@
import path from 'path'; import path from 'path';
import addLeadingSlash from '../utils/addLeadingSlash.js';
function getMatchingEntries(entry, entries) { function getMatchingEntries(entry, entries) {
const dirname = entry.name || '.'; const dirname = entry.name || '.';
@ -10,9 +8,11 @@ function getMatchingEntries(entry, entries) {
.map(name => entries[name]); .map(name => entries[name]);
} }
const leadingSlashes = /^\/*/;
function getMetadata(entry, entries) { function getMetadata(entry, entries) {
const metadata = { const metadata = {
path: addLeadingSlash(entry.name), path: entry.name.replace(leadingSlashes, '/'),
type: entry.type type: entry.type
}; };

View File

@ -1,4 +1,3 @@
import addLeadingSlash from '../utils/addLeadingSlash.js';
import createPackageURL from '../utils/createPackageURL.js'; import createPackageURL from '../utils/createPackageURL.js';
import createSearch from '../utils/createSearch.js'; import createSearch from '../utils/createSearch.js';
import { getPackageConfig, resolveVersion } from '../utils/npm.js'; import { getPackageConfig, resolveVersion } from '../utils/npm.js';
@ -15,6 +14,8 @@ function semverRedirect(req, res, newVersion) {
); );
} }
const leadingSlashes = /^\/*/;
function filenameRedirect(req, res) { function filenameRedirect(req, res) {
let filename; let filename;
if (req.query.module != null) { if (req.query.module != null) {
@ -75,7 +76,7 @@ function filenameRedirect(req, res) {
createPackageURL( createPackageURL(
req.packageName, req.packageName,
req.packageVersion, req.packageVersion,
addLeadingSlash(filename), filename.replace(leadingSlashes, '/'),
createSearch(req.query) createSearch(req.query)
) )
); );

View File

@ -2,12 +2,17 @@ import path from 'path';
import gunzip from 'gunzip-maybe'; import gunzip from 'gunzip-maybe';
import tar from 'tar-stream'; import tar from 'tar-stream';
import addLeadingSlash from '../utils/addLeadingSlash.js';
import createPackageURL from '../utils/createPackageURL.js'; import createPackageURL from '../utils/createPackageURL.js';
import createSearch from '../utils/createSearch.js'; import createSearch from '../utils/createSearch.js';
import { getPackage } from '../utils/npm.js'; import { getPackage } from '../utils/npm.js';
import getIntegrity from '../utils/getIntegrity.js'; import getIntegrity from '../utils/getIntegrity.js';
import getContentType from '../utils/getContentType.js'; import getContentType from '../utils/getContentType.js';
import bufferStream from '../utils/bufferStream.js';
const leadingSlashes = /^\/*/;
const multipleSlashes = /\/*/;
const trailingSlashes = /\/*$/;
const leadingSegment = /^[^/]+\/?/;
function fileRedirect(req, res, entry) { function fileRedirect(req, res, entry) {
// Redirect to the file with the extension so it's more // Redirect to the file with the extension so it's more
@ -22,7 +27,7 @@ function fileRedirect(req, res, entry) {
createPackageURL( createPackageURL(
req.packageName, req.packageName,
req.packageVersion, req.packageVersion,
addLeadingSlash(entry.name), entry.name.replace(leadingSlashes, '/'),
createSearch(req.query) createSearch(req.query)
) )
); );
@ -41,23 +46,19 @@ function indexRedirect(req, res, entry) {
createPackageURL( createPackageURL(
req.packageName, req.packageName,
req.packageVersion, req.packageVersion,
addLeadingSlash(entry.name), entry.name.replace(leadingSlashes, '/'),
createSearch(req.query) createSearch(req.query)
) )
); );
} }
function stripLeadingSegment(name) {
return name.replace(/^[^/]+\/?/, '');
}
/** /**
* Search the given tarball for entries that match the given name. * Search the given tarball for entries that match the given name.
* Follows node's resolution algorithm. * Follows node's resolution algorithm.
* https://nodejs.org/api/modules.html#modules_all_together * https://nodejs.org/api/modules.html#modules_all_together
*/ */
function searchEntries(stream, entryName, wantsIndex) { function searchEntries(stream, entryName, wantsIndex) {
return new Promise((resolve, reject) => { return new Promise((accept, reject) => {
const jsEntryName = `${entryName}.js`; const jsEntryName = `${entryName}.js`;
const jsonEntryName = `${entryName}.json`; const jsonEntryName = `${entryName}.json`;
const entries = {}; const entries = {};
@ -72,13 +73,13 @@ function searchEntries(stream, entryName, wantsIndex) {
.pipe(gunzip()) .pipe(gunzip())
.pipe(tar.extract()) .pipe(tar.extract())
.on('error', reject) .on('error', reject)
.on('entry', (header, stream, next) => { .on('entry', async (header, stream, next) => {
const entry = { const entry = {
// Most packages have header names that look like `package/index.js` // Most packages have header names that look like `package/index.js`
// so we shorten that to just `index.js` here. A few packages use a // so we shorten that to just `index.js` here. A few packages use a
// prefix other than `package/`. e.g. the firebase package uses the // prefix other than `package/`. e.g. the firebase package uses the
// `firebase_npm/` prefix. So we just strip the first dir name. // `firebase_npm/` prefix. So we just strip the first dir name.
name: stripLeadingSegment(header.name), name: header.name.replace(leadingSegment, ''),
type: header.type type: header.type
}; };
@ -124,33 +125,25 @@ function searchEntries(stream, entryName, wantsIndex) {
} }
} }
const chunks = []; const content = await bufferStream(stream);
stream // Set some extra properties for files that we will
.on('data', chunk => { // need to serve them and for ?meta listings.
chunks.push(chunk); entry.contentType = getContentType(entry.name);
}) entry.integrity = getIntegrity(content);
.on('end', () => { entry.lastModified = header.mtime.toUTCString();
const content = Buffer.concat(chunks); entry.size = content.length;
// Set some extra properties for files that we will // Set the content only for the foundEntry and
// need to serve them and for ?meta listings. // discard the buffer for all others.
entry.contentType = getContentType(entry.name); if (entry === foundEntry) {
entry.integrity = getIntegrity(content); entry.content = content;
entry.lastModified = header.mtime.toUTCString(); }
entry.size = content.length;
// Set the content only for the foundEntry and next();
// discard the buffer for all others.
if (entry === foundEntry) {
entry.content = content;
}
next();
});
}) })
.on('finish', () => { .on('finish', () => {
resolve({ accept({
entries, entries,
// If we didn't find a matching file entry, // If we didn't find a matching file entry,
// try a directory entry with the same name. // try a directory entry with the same name.
@ -160,22 +153,18 @@ function searchEntries(stream, entryName, wantsIndex) {
}); });
} }
const leadingSlash = /^\//;
const multipleSlash = /\/\/+/;
const trailingSlash = /\/$/;
/** /**
* Fetch and search the archive to try and find the requested file. * Fetch and search the archive to try and find the requested file.
* Redirect to the "index" file if a directory was requested. * Redirect to the "index" file if a directory was requested.
*/ */
export default async function findFile(req, res, next) { export default async function findFile(req, res, next) {
const wantsIndex = trailingSlash.test(req.filename); const wantsIndex = req.filename.endsWith('/');
// The name of the file/directory we're looking for. // The name of the file/directory we're looking for.
const entryName = req.filename const entryName = req.filename
.replace(multipleSlash, '/') .replace(multipleSlashes, '/')
.replace(trailingSlash, '') .replace(trailingSlashes, '')
.replace(leadingSlash, ''); .replace(leadingSlashes, '');
const stream = await getPackage(req.packageName, req.packageVersion); const stream = await getPackage(req.packageName, req.packageVersion);
const { entries, foundEntry } = await searchEntries( const { entries, foundEntry } = await searchEntries(

View File

@ -1,3 +0,0 @@
export default function addLeadingSlash(name) {
return name.charAt(0) === '/' ? name : '/' + name;
}