Skip to content

Commit

Permalink
Support for custom headers added
Browse files Browse the repository at this point in the history
  • Loading branch information
leo committed May 19, 2018
1 parent 82fd55a commit db9f83b
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 26 deletions.
110 changes: 85 additions & 25 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,45 +5,66 @@ const path = require('path');
const url = require('fast-url-parser');
const fs = require('fs-extra');
const slasher = require('glob-slasher');
const minimatch = require('minimatch');
const pathToRegExp = require('path-to-regexp');
const mime = require('mime/lite');

const getHandlers = methods => {
const {createReadStream} = fs;
const {stat, createReadStream} = fs;

return Object.assign({
stat,
createReadStream
}, methods);
};

const toRegExp = (location, keys = null) => {
const normalized = slasher(location).replace('*', '(.*)');
return pathToRegExp(normalized, keys);
const sourceMatches = (source, requestPath, allowSegments) => {
const keys = [];
const slashed = slasher(source);

let results = null;

if (allowSegments) {
const normalized = slashed.replace('*', '(.*)');
const expression = pathToRegExp(normalized, keys);

results = expression.exec(requestPath);
}

if (results || minimatch(requestPath, slashed)) {
return {
keys,
results
};
}

return null;
};

const toTarget = (source, destination, previousPath) => {
const keys = [];
const expression = toRegExp(source, keys);
const results = expression.exec(previousPath);

if (results) {
const props = {};
const {protocol} = url.parse(destination);
const normalizedDest = protocol ? destination : slasher(destination);
const toPath = pathToRegExp.compile(normalizedDest);

for (let index = 0; index < keys.length; index++) {
const {name} = keys[index];
props[name] = results[index + 1];
}
const matches = sourceMatches(source, previousPath, true);

return toPath(props);
if (!matches) {
return null;
}

return null;
const {keys, results} = matches;

const props = {};
const {protocol} = url.parse(destination);
const normalizedDest = protocol ? destination : slasher(destination);
const toPath = pathToRegExp.compile(normalizedDest);

for (let index = 0; index < keys.length; index++) {
const {name} = keys[index];
props[name] = results[index + 1];
}

return toPath(props);
};

const applyRewrites = (requestPath, rewrites) => {
if (!Array.isArray(rewrites)) {
const applyRewrites = (requestPath, rewrites = []) => {
if (rewrites.length === 0) {
return requestPath;
}

Expand All @@ -59,8 +80,8 @@ const applyRewrites = (requestPath, rewrites) => {
return requestPath;
};

const applyRedirect = (rewrittenURL, redirects) => {
if (!Array.isArray(redirects)) {
const applyRedirect = (rewrittenURL, redirects = []) => {
if (redirects.length === 0) {
return null;
}

Expand All @@ -81,6 +102,40 @@ const applyRedirect = (rewrittenURL, redirects) => {
return null;
};

const appendHeaders = (target, source) => {
for (let index = 0; index < source.length; index++) {
const {key, value} = source[index];
target[key] = value;
}
};

const getHeaders = async (handlers, customHeaders = [], {relative, absolute}) => {
const related = {};

if (customHeaders.length > 0) {
// By iterating over all headers and never stopping, developers
// can specify multiple header sources in the config that
// might match a single path.
for (let index = 0; index < customHeaders.length; index++) {
const {source, headers} = customHeaders[index];

if (sourceMatches(source, relative)) {
appendHeaders(related, headers);
}
}
}

const stats = await handlers.stat(absolute);

const defaultHeaders = {
'Content-Type': mime.getType(relative),
'Last-Modified': stats.mtime.toUTCString(),
'Content-Length': stats.size
};

return Object.assign(defaultHeaders, related);
};

module.exports = async (request, response, config = {}, methods) => {
const cwd = process.cwd();
const current = config.path ? path.join(cwd, config.path) : cwd;
Expand All @@ -102,7 +157,12 @@ module.exports = async (request, response, config = {}, methods) => {
const relatedExists = await fs.exists(related);

if (relatedExists) {
// response.writeHead(200, getHeaders(related));
const headers = await getHeaders(handlers, config.headers, {
relative: rewrittenURL,
absolute: related
});

response.writeHead(200, headers);
handlers.createReadStream(related).pipe(response);

return;
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"fs-extra": "6.0.1",
"glob-slasher": "1.0.1",
"mime": "2.3.1",
"minimatch": "3.0.4",
"path-to-regexp": "2.2.1"
}
}
2 changes: 1 addition & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,7 @@ mimic-fn@^1.0.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022"

minimatch@^3.0.2, minimatch@^3.0.4:
minimatch@3.0.4, minimatch@^3.0.2, minimatch@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
dependencies:
Expand Down

0 comments on commit db9f83b

Please sign in to comment.