Socket
Socket
Sign inDemoInstall

serve-handler

Package Overview
Dependencies
19
Maintainers
1
Versions
65
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 2.0.0 to 2.1.0

12

package.json
{
"name": "serve-handler",
"version": "2.0.0",
"version": "2.1.0",
"description": "The routing foundation of `serve` and static deployments on Now",

@@ -9,3 +9,5 @@ "main": "src/index.js",

"lint": "zeit-eslint --ext .jsx,.js .",
"lint-staged": "git diff --diff-filter=ACMRT --cached --name-only '*.js' '*.jsx' | xargs zeit-eslint"
"lint-staged": "git diff --diff-filter=ACMRT --cached --name-only '*.js' '*.jsx' | xargs zeit-eslint",
"build-views": "dottojs -s ./src -d ./src",
"prepublish": "yarn run build-views"
},

@@ -20,5 +22,10 @@ "repository": "zeit/serve-handler",

"license": "MIT",
"files": [
"./src/*.js"
],
"devDependencies": {
"@zeit/eslint-config-node": "0.2.13",
"@zeit/git-hooks": "0.1.4",
"commander": "2.15.1",
"dot": "1.1.2",
"eslint": "4.19.1"

@@ -35,2 +42,3 @@ },

"dependencies": {
"bytes": "3.0.0",
"fast-url-parser": "1.1.3",

@@ -37,0 +45,0 @@ "fs-extra": "6.0.1",

@@ -53,2 +53,3 @@ # serve-handler

- [headers](#headers-array) (set custom headers)
- [directoryListing](#trailingslash-boolean) (disable directory listing or restrict it to certain paths)
- [trailingSlash](#trailingslash-boolean) (remove or add trailing slashes to all paths)

@@ -170,2 +171,17 @@

### directoryListing (Boolean|Array)
For paths are not files, but directories, the package will automatically render a good-looking list of all the files and directories contained inside that directory.
If you'd like to disable this for all paths, set this option to `false`. Furthermore, you can also restrict it to certain directory paths if you want:
```json
{
"directoryListing": [
"/assets/**",
"/!assets/private"
]
}
```
### trailingSlash (Boolean)

@@ -193,4 +209,5 @@

await handler(request, response, null, {
stat(path) {},
createReadStream(path) {},
stat(path) {}
readdir(path) {}
});

@@ -197,0 +214,0 @@ ```

@@ -11,9 +11,14 @@ // Native

const mime = require('mime/lite');
const bytes = require('bytes');
// Other
const template = require('./directory.js');
const getHandlers = methods => {
const {stat, createReadStream} = fs;
const {stat, createReadStream, readdir} = fs;
return Object.assign({
stat,
createReadStream
createReadStream,
readdir
}, methods);

@@ -158,3 +163,3 @@ };

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

@@ -184,12 +189,12 @@

const applicableForCleanUrl = (decodedPath, cleanUrls) => {
let matches = false;
const applicable = (decodedPath, configEntry, negative) => {
let matches = negative ? false : true;
if (typeof cleanUrls !== 'undefined') {
matches = (cleanUrls === true);
if (typeof configEntry !== 'undefined') {
matches = (configEntry === !negative);
if (!matches && Array.isArray(cleanUrls)) {
if (!matches && Array.isArray(configEntry)) {
// This is much faster than `.some`
for (let index = 0; index < cleanUrls.length; index++) {
const source = cleanUrls[index];
for (let index = 0; index < configEntry.length; index++) {
const source = configEntry[index];

@@ -251,2 +256,93 @@ if (sourceMatches(source, decodedPath)) {

const renderDirectory = async (current, relativePath, absolutePath, {readdir, stat}) => {
let files = await readdir(absolutePath);
for (const file of files) {
const filePath = path.resolve(absolutePath, file);
const details = path.parse(filePath);
const stats = await stat(filePath);
details.relative = path.join(relativePath, details.base);
if (stats.isDirectory()) {
details.base += '/';
} else {
details.ext = details.ext.split('.')[1] || 'txt';
details.size = bytes(stats.size, {unitSeparator: ' '});
}
details.title = details.base;
files[files.indexOf(file)] = details;
}
const directory = path.join(path.basename(current), relativePath, '/');
const pathParts = directory.split(path.sep);
// Sort to list directories first, then sort alphabetically
files = files.sort((a, b) => {
const aIsDir = a.base.endsWith('/');
const bIsDir = b.base.endsWith('/');
if (aIsDir && !bIsDir) {
return -1;
}
if (bIsDir && !aIsDir) {
return 1;
}
if (a.base > b.base) {
return 1;
}
if (a.base < b.base) {
return -1;
}
return 0;
});
// Add parent directory to the head of the sorted files array
if (absolutePath.indexOf(`${current}/`) > -1) {
const directoryPath = [...pathParts];
directoryPath.shift();
files.unshift({
base: '..',
relative: path.join(...directoryPath, '..'),
title: path.join(...pathParts.slice(0, -2), '/')
});
}
const paths = [];
pathParts.pop();
for (const part in pathParts) {
if (!{}.hasOwnProperty.call(pathParts, part)) {
continue;
}
let before = 0;
const parents = [];
while (before <= part) {
parents.push(pathParts[before]);
before++;
}
parents.shift();
paths.push({
name: pathParts[part],
url: parents.join('/')
});
}
return template({
files,
directory,
paths
});
};
module.exports = async (request, response, config = {}, methods = {}) => {

@@ -258,3 +354,3 @@ const cwd = process.cwd();

const decodedPath = decodeURIComponent(url.parse(request.url).pathname);
const cleanUrl = applicableForCleanUrl(decodedPath, config.cleanUrls);
const cleanUrl = applicable(decodedPath, config.cleanUrls, true);
const redirect = shouldRedirect(decodedPath, config, cleanUrl);

@@ -312,3 +408,3 @@

const headers = await getHeaders(handlers, config.headers, relativePath, stats);
const headers = await getHeaders(config.headers, relativePath, stats);

@@ -322,4 +418,24 @@ if (stats.isFile()) {

const canList = applicable(decodedPath, config.directoryListing, false);
if (!canList) {
response.statusCode = 404;
response.end('Not Found');
return;
}
let directory = null;
try {
directory = await renderDirectory(current, relativePath, absolutePath, handlers);
} catch (err) {
response.statusCode = 500;
response.end(err.message);
return;
}
response.statusCode = 200;
response.end('Directory');
response.end(directory);
};
.circleci/config.yml
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc