1 |
|
2 | /*!
|
3 | * Connect - limit
|
4 | * Copyright(c) 2011 TJ Holowaychuk
|
5 | * MIT Licensed
|
6 | */
|
7 |
|
8 | /**
|
9 | * Module dependencies.
|
10 | */
|
11 |
|
12 | var createError = require('http-errors');
|
13 | var deprecate = require('depd')('connect');
|
14 | var parseBytes = require('bytes');
|
15 | var utils = require('../utils');
|
16 | var brokenPause = utils.brokenPause;
|
17 |
|
18 | /**
|
19 | * Limit:
|
20 | *
|
21 | * Status: Deprecated. This middleware will be removed in Connect 3.0.
|
22 | * If you still wish to use some type of limit middleware,
|
23 | * you may be interested in:
|
24 | *
|
25 | * - [raw-body](https://github.com/stream-utils/raw-body)
|
26 | *
|
27 | * Limit request bodies to the given size in `bytes`.
|
28 | *
|
29 | * A string representation of the bytesize may also be passed,
|
30 | * for example "5mb", "200kb", "1gb", etc.
|
31 | *
|
32 | * connect()
|
33 | * .use(connect.limit('5.5mb'))
|
34 | * .use(handleImageUpload)
|
35 | *
|
36 | * @param {Number|String} bytes
|
37 | * @return {Function}
|
38 | * @api public
|
39 | */
|
40 |
|
41 | module.exports = function limit(bytes){
|
42 | if ('string' == typeof bytes) bytes = parseBytes(bytes);
|
43 | if ('number' != typeof bytes) throw new Error('limit() bytes required');
|
44 |
|
45 | return function limit(req, res, next){
|
46 | var received = 0
|
47 | , len = req.headers['content-length']
|
48 | ? parseInt(req.headers['content-length'], 10)
|
49 | : null;
|
50 |
|
51 | // self-awareness
|
52 | if (req._limit) return next();
|
53 | req._limit = true;
|
54 |
|
55 | // limit by content-length
|
56 | if (len && len > bytes) return next(createError(413));
|
57 |
|
58 | // limit
|
59 | if (brokenPause) {
|
60 | listen();
|
61 | } else {
|
62 | req.on('newListener', function handler(event) {
|
63 | if (event !== 'data') return;
|
64 |
|
65 | req.removeListener('newListener', handler);
|
66 | // Start listening at the end of the current loop
|
67 | // otherwise the request will be consumed too early.
|
68 | // Sideaffect is `limit` will miss the first chunk,
|
69 | // but that's not a big deal.
|
70 | // Unfortunately, the tests don't have large enough
|
71 | // request bodies to test this.
|
72 | process.nextTick(listen);
|
73 | });
|
74 | };
|
75 |
|
76 | next();
|
77 |
|
78 | function listen() {
|
79 | req.on('data', function(chunk) {
|
80 | received += Buffer.isBuffer(chunk)
|
81 | ? chunk.length :
|
82 | Buffer.byteLength(chunk);
|
83 |
|
84 | if (received > bytes) req.destroy();
|
85 | });
|
86 | };
|
87 | };
|
88 | };
|
89 |
|
90 | module.exports = deprecate.function(module.exports,
|
91 | 'limit: Restrict request size at location of read');
|