Comparing version 3.3.0 to 4.0.0
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 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
135
10441
103
1
+ Addedhttp-errors@^1.6.1
+ Addedhttp-errors@1.8.1(transitive)
+ Addedinherits@2.0.4(transitive)
+ Addedsetprototypeof@1.2.0(transitive)
+ Addedtoidentifier@1.0.1(transitive)
- Removedco@^4.6.0
- Removedco@4.6.0(transitive)
Updateddebug@^2.6.3
Updatedmz@^2.6.0
Updatedresolve-path@^1.3.3