Socket
Socket
Sign inDemoInstall

koa-send

Package Overview
Dependencies
Maintainers
9
Versions
28
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

koa-send - npm Package Compare versions

Comparing version 3.3.0 to 4.0.0

7

History.md
4.0.0 / 2017-04-09
==================
* throw error if file not exists, closes #43
* remove co, use async function
* bump deps
3.3.0 / 2017-01-10

@@ -3,0 +10,0 @@ ==================

177

index.js

@@ -5,15 +5,17 @@ /**

var debug = require('debug')('koa-send');
var resolvePath = require('resolve-path');
var assert = require('assert');
var path = require('path');
var normalize = path.normalize;
var basename = path.basename;
var extname = path.extname;
var resolve = path.resolve;
var parse = path.parse;
var sep = path.sep;
var fs = require('mz/fs');
var co = require('co');
const debug = require('debug')('koa-send');
const resolvePath = require('resolve-path');
const createError = require('http-errors');
const assert = require('assert');
const fs = require('mz/fs');
const {
normalize,
basename,
extname,
resolve,
parse,
sep
} = require('path');
/**

@@ -36,96 +38,95 @@ * Expose `send()`.

function send(ctx, path, opts) {
return co(function *(){
async function send(ctx, path, opts = {}) {
assert(ctx, 'koa context required');
assert(path, 'pathname required');
assert(ctx, 'koa context required');
assert(path, 'pathname required');
opts = opts || {};
// options
debug('send "%s" %j', path, opts);
const root = opts.root ? normalize(resolve(opts.root)) : '';
const trailingSlash = '/' == path[path.length - 1];
path = path.substr(parse(path).root.length);
const index = opts.index;
const maxage = opts.maxage || opts.maxAge || 0;
const hidden = opts.hidden || false;
const format = opts.format === false ? false : true;
const extensions = Array.isArray(opts.extensions) ? opts.extensions : false;
const gzip = opts.gzip === false ? false : true;
const setHeaders = opts.setHeaders;
// options
debug('send "%s" %j', path, opts);
var root = opts.root ? normalize(resolve(opts.root)) : '';
var trailingSlash = '/' == path[path.length - 1];
path = path.substr(parse(path).root.length);
var index = opts.index;
var maxage = opts.maxage || opts.maxAge || 0;
var hidden = opts.hidden || false;
var format = opts.format === false ? false : true;
var extensions = Array.isArray(opts.extensions) ? opts.extensions : false;
var gzip = opts.gzip === false ? false : true;
var setHeaders = opts.setHeaders;
if (setHeaders && typeof setHeaders !== 'function') {
throw new TypeError('option setHeaders must be function')
}
if (setHeaders && typeof setHeaders !== 'function') {
throw new TypeError('option setHeaders must be function')
}
const encoding = ctx.acceptsEncodings('gzip', 'deflate', 'identity');
var encoding = ctx.acceptsEncodings('gzip', 'deflate', 'identity');
// normalize path
path = decode(path);
// normalize path
path = decode(path);
if (-1 == path) return ctx.throw(400, 'failed to decode');
if (-1 == path) return ctx.throw('failed to decode', 400);
// index file support
if (index && trailingSlash) path += index;
// index file support
if (index && trailingSlash) path += index;
path = resolvePath(root, path);
path = resolvePath(root, path);
// hidden file support, ignore
if (!hidden && isHidden(root, path)) return;
// hidden file support, ignore
if (!hidden && isHidden(root, path)) return;
// serve gzipped file when possible
if (encoding === 'gzip' && gzip && (await fs.exists(path + '.gz'))) {
path = path + '.gz';
ctx.set('Content-Encoding', 'gzip');
ctx.res.removeHeader('Content-Length');
}
// serve gzipped file when possible
if (encoding === 'gzip' && gzip && (yield fs.exists(path + '.gz'))) {
path = path + '.gz';
ctx.set('Content-Encoding', 'gzip');
ctx.res.removeHeader('Content-Length');
}
if (extensions && !/\..*$/.exec(path)) {
var list = [].concat(extensions);
for (var i = 0; i < list.length; i++) {
var ext = list[i];
if (typeof ext !== 'string') {
throw new TypeError('option extensions must be array of strings or false');
}
if (!/^\./.exec(ext)) ext = '.' + ext;
if (yield fs.exists(path + ext)) {
path = path + ext;
break;
}
if (extensions && !/\..*$/.exec(path)) {
const list = [].concat(extensions);
for (let i = 0; i < list.length; i++) {
let ext = list[i];
if (typeof ext !== 'string') {
throw new TypeError('option extensions must be array of strings or false');
}
if (!/^\./.exec(ext)) ext = '.' + ext;
if (await fs.exists(path + ext)) {
path = path + ext;
break;
}
}
}
// stat
try {
var stats = yield fs.stat(path);
// stat
let stats
try {
stats = await fs.stat(path);
// Format the path to serve static file servers
// and not require a trailing slash for directories,
// so that you can do both `/directory` and `/directory/`
if (stats.isDirectory()) {
if (format && index) {
path += '/' + index;
stats = yield fs.stat(path);
} else {
return;
}
// Format the path to serve static file servers
// and not require a trailing slash for directories,
// so that you can do both `/directory` and `/directory/`
if (stats.isDirectory()) {
if (format && index) {
path += '/' + index;
stats = await fs.stat(path);
} else {
return;
}
} catch (err) {
var notfound = ['ENOENT', 'ENAMETOOLONG', 'ENOTDIR'];
if (~notfound.indexOf(err.code)) return;
err.status = 500;
throw err;
}
} catch (err) {
const notfound = ['ENOENT', 'ENAMETOOLONG', 'ENOTDIR'];
if (notfound.includes(err.code)) {
throw createError(404, err);
}
err.status = 500;
throw err;
}
if (setHeaders) setHeaders(ctx.res, path, stats);
if (setHeaders) setHeaders(ctx.res, path, stats);
// stream
ctx.set('Content-Length', stats.size);
if (!ctx.response.get('Last-Modified')) ctx.set('Last-Modified', stats.mtime.toUTCString());
if (!ctx.response.get('Cache-Control')) ctx.set('Cache-Control', 'max-age=' + (maxage / 1000 | 0));
ctx.type = type(path);
ctx.body = fs.createReadStream(path);
// stream
ctx.set('Content-Length', stats.size);
if (!ctx.response.get('Last-Modified')) ctx.set('Last-Modified', stats.mtime.toUTCString());
if (!ctx.response.get('Cache-Control')) ctx.set('Cache-Control', 'max-age=' + (maxage / 1000 | 0));
ctx.type = type(path);
ctx.body = fs.createReadStream(path);
return path;
});
return path;
}

@@ -139,3 +140,3 @@

path = path.substr(root.length).split(sep);
for(var i = 0; i < path.length; i++) {
for(let i = 0; i < path.length; i++) {
if(path[i][0] === '.') return true;

@@ -142,0 +143,0 @@ }

@@ -5,3 +5,3 @@ {

"repository": "koajs/send",
"version": "3.3.0",
"version": "4.0.0",
"keywords": [

@@ -18,13 +18,13 @@ "koa",

"istanbul": "0",
"koa": "1",
"koa": "2",
"mocha": "3",
"should": "11",
"supertest": "2"
"supertest": "3"
},
"license": "MIT",
"dependencies": {
"co": "^4.6.0",
"debug": "^2.6.0",
"mz": "^2.3.1",
"resolve-path": "^1.3.1"
"debug": "^2.6.3",
"http-errors": "^1.6.1",
"mz": "^2.6.0",
"resolve-path": "^1.3.3"
},

@@ -35,3 +35,6 @@ "scripts": {

"test-travis": "istanbul cover ./node_modules/.bin/_mocha --report lcovonly -- --require should"
},
"engines": {
"node": ">= 7.6.0"
}
}

@@ -40,4 +40,4 @@

```js
app.use(function *(){
yield send(this, this.path, { root: __dirname + '/public' });
app.use(async (ctx) => {
await send(ctx, ctx.path, { root: __dirname + '/public' });
})

@@ -49,4 +49,4 @@ ```

```js
app.use(function *(){
yield send(this, 'path/to/my.js');
app.use(async (ctx) => {
await send(ctx, 'path/to/my.js');
})

@@ -66,8 +66,8 @@ ```

## Example (Koa@2) with async/await
## Example
```js
var send = require('koa-send');
var Koa = require('koa');
var app = new Koa();
const send = require('koa-send');
const Koa = require('koa');
const app = new Koa();

@@ -77,3 +77,3 @@ // $ GET /package.json

app.use(async function (ctx, next){
app.use(async (ctx) => {
if ('/' == ctx.path) return ctx.body = 'Try GET /package.json';

@@ -87,21 +87,2 @@ await send(ctx, ctx.path);

## Example
```js
var send = require('koa-send');
var koa = require('koa');
var app = koa();
// $ GET /package.json
// $ GET /
app.use(function *(){
if ('/' == this.path) return this.body = 'Try GET /package.json';
yield send(this, this.path);
})
app.listen(3000);
console.log('listening on port 3000');
```
## License

@@ -108,0 +89,0 @@

SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc