in src/middleware/files.js [22:173]
module.exports = function() {
return function(req, res, next) {
const config = req.superstatic;
const trailingSlashBehavior = config.trailingSlash;
const parsedUrl = url.parse(req.url);
const pathname = pathutils.normalizeMultiSlashes(parsedUrl.pathname);
const search = parsedUrl.search || "";
const cleanUrlRules = !!_.get(req, "superstatic.cleanUrls");
// Exact file always wins.
return providerResult(req, res, pathname)
.then((result) => {
if (result) {
// If we are using cleanURLs, we'll trim off any `.html` (or `/index.html`), if it exists.
if (cleanUrlRules) {
if (_.endsWith(pathname, ".html")) {
let redirPath = pathutils.removeTrailingString(pathname, ".html");
if (_.endsWith(redirPath, "/index")) {
redirPath = pathutils.removeTrailingString(redirPath, "/index");
}
if (trailingSlashBehavior === true) {
redirPath = pathutils.addTrailingSlash(redirPath);
}
return res.superstatic.handle({
redirect: normalizeRedirectPath(redirPath + search)
});
}
}
return res.superstatic.handleFileStream({ file: pathname }, result);
}
// Now, let's consider the trailing slash.
const hasTrailingSlash = pathutils.hasTrailingSlash(pathname);
// We want to check for some other files, namely an `index.html` if this were a directory.
const pathAsDirectoryWithIndex = pathutils.asDirectoryIndex(
pathutils.addTrailingSlash(pathname)
);
return providerResult(req, res, pathAsDirectoryWithIndex).then(
(pathAsDirectoryWithIndexResult) => {
// If an exact file wins now, we know that this path leads us to a directory.
if (pathAsDirectoryWithIndexResult) {
if (
trailingSlashBehavior === undefined &&
!hasTrailingSlash &&
!cleanUrlRules
) {
return res.superstatic.handle({
redirect: pathutils.addTrailingSlash(pathname) + search
});
}
if (
trailingSlashBehavior === false &&
hasTrailingSlash &&
pathname !== "/"
) {
// No infinite redirects
return res.superstatic.handle({
redirect: normalizeRedirectPath(
pathutils.removeTrailingSlash(pathname) + search
)
});
}
if (trailingSlashBehavior === true && !hasTrailingSlash) {
return res.superstatic.handle({
redirect: pathutils.addTrailingSlash(pathname) + search
});
}
// If we haven't returned yet, our path is "correct" and we should be serving a file, not redirecting.
return res.superstatic.handleFileStream(
{ file: pathAsDirectoryWithIndex },
pathAsDirectoryWithIndexResult
);
}
// Let's check on the clean URLs property.
// We want to know if a specific mutation of the path exists.
if (cleanUrlRules) {
let appendedPath = pathname;
if (hasTrailingSlash) {
if (trailingSlashBehavior !== undefined) {
// We want to remove the trailing slash and see if a file exists with an .html attached.
appendedPath =
pathutils.removeTrailingString(pathname, "/") + ".html";
}
} else {
// Let's see if our path is a simple clean URL missing a .HTML5
appendedPath += ".html";
}
return providerResult(req, res, appendedPath).then(
(appendedPathResult) => {
if (appendedPathResult) {
// Okay, back to trailing slash behavior
if (trailingSlashBehavior === false && hasTrailingSlash) {
// If we had a slash to begin with, and we could be serving a file without it, we'll remove the slash.
// (This works because we are in the cleanURL block.)
return res.superstatic.handle({
redirect: normalizeRedirectPath(
pathutils.removeTrailingSlash(pathname) + search
)
});
}
if (trailingSlashBehavior === true && !hasTrailingSlash) {
// If we are missing a slash and need to add it, we want to make sure our appended path is cleaned up.
appendedPath = pathutils.removeTrailingString(
appendedPath,
".html"
);
appendedPath = pathutils.removeTrailingString(
appendedPath,
"/index"
);
return res.superstatic.handle({
redirect:
pathutils.addTrailingSlash(appendedPath) + search
});
}
// If we've gotten this far and still have `/index.html` on the end, we want to remove it from the URL.
if (_.endsWith(appendedPath, "/index.html")) {
return res.superstatic.handle({
redirect: normalizeRedirectPath(
pathutils.removeTrailingString(
appendedPath,
"/index.html"
) + search
)
});
}
// And if we should be serving a file and we're at the right path, we'll serve the file.
return res.superstatic.handleFileStream(
{ file: appendedPath },
appendedPathResult
);
}
return next();
}
);
}
return next();
}
);
})
.catch((err) => {
res.superstatic.handleError(err);
});
};
};