Skip to content

Instantly share code, notes, and snippets.

@shigeki
Last active December 28, 2015 18:09
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shigeki/7540543 to your computer and use it in GitHub Desktop.
Save shigeki/7540543 to your computer and use it in GitHub Desktop.
Post Upload Control: File size check
var stream = require('stream');
var express = require('express');
var multiparty = require('multiparty');
var app = express();
var maxlimit = 2 * 1024 * 1024; // 2M byte
var postHandler = function(req, res, next) {
var length = 0;
var buflist = [];
var content_length = req.get('content-length');
// Request Entity Too Large error due to Content-Length
if (content_length !== undefined && +content_length > maxlimit) {
console.log('POST upload failed. content-length=', content_length);
res.send(413);
return;
}
var form = new multiparty.Form({uploadDir: './uploaded'});
// fake request object of http.IncomingMessage
var fake_request = new stream.PassThrough();
fake_request.httpVersion = req.httpVersion;
fake_request.headers = req.headers;
fake_request.trailers = req.trailers;
fake_request.method = req.method;
fake_request.url = req.url;
fake_request.socket = req.socket;
fake_request.setTimeout = req.setTimeout;
form.parse(fake_request, function(err, fields, files) {
if (err) {
console.log('Post upload failed. err=', err);
return;
}
console.log('Post upload succeeded. files=', files);
res.send(204);
});
var wstream = new stream.Writable();
wstream._write = function(chunk, encoding, cb) {
if (chunk === null || req.error) return;
length += chunk.length;
// Request Entity Too Large error via Transfer-Encoding: chunked
if (length > maxlimit) {
res.send(413);
req.error = true;
console.log('Post upload failed. length=', length);
return;
}
buflist.push(chunk);
cb();
};
wstream.on('finish', function() {
if (req.error) return;
// Pass the content length check so that form will be parsed
fake_request.write(Buffer.concat(buflist));
});
req.pipe(wstream);
};
app.configure(function() {
app.post('/', postHandler);
});
app.listen(3000);

Content-Length付き 1Mbyte Upload結果

ohtsu@unix:~/tmp/post_test$ curl -v -H "Expect:" localhost:3000 -X POST  -F 'file=@1M.file'
* Rebuilt URL to: localhost:3000/
* Adding handle: conn: 0x1729b20
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x1729b20) send_pipe: 1, recv_pipe: 0
* About to connect() to localhost port 3000 (#0)
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 3000 (#0)
> POST / HTTP/1.1
> User-Agent: curl/7.32.0
> Host: localhost:3000
> Accept: */*
> Content-Length: 1048775
> Content-Type: multipart/form-data; boundary=------------------------83e51df6e3c3160b
>
< HTTP/1.1 204 No Content
< X-Powered-By: Express
< Date: Tue, 19 Nov 2013 04:50:13 GMT
< Connection: keep-alive
<
* Connection #0 to host localhost left intact

ohtsu@unix:~/tmp/post_test$ ls -l uploaded/
total 1024
-rw-rw-r-- 1 ohtsu ohtsu 1048576 Nov 19 13:50 2285-1zhfgd.file

Content-Length付き 3Mbyte Upload結果

ohtsu@unix:~/tmp/post_test$ curl -v -H "Expect:" localhost:3000 -X POST  -F 'file=@3M.file'
* Rebuilt URL to: localhost:3000/
* Adding handle: conn: 0x2548b20
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x2548b20) send_pipe: 1, recv_pipe: 0
* About to connect() to localhost port 3000 (#0)
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 3000 (#0)
> POST / HTTP/1.1
> User-Agent: curl/7.32.0
> Host: localhost:3000
> Accept: */*
> Content-Length: 3145927
> Content-Type: multipart/form-data; boundary=------------------------63ad62f55967b697
>
< HTTP/1.1 413 Request Entity Too Large
< X-Powered-By: Express
< Content-Type: text/plain
< Content-Length: 24
< Date: Tue, 19 Nov 2013 04:50:21 GMT
< Connection: keep-alive
* HTTP error before end of send, stop sending
<
* Closing connection 0
Request Entity Too Large

Transfer-Encoding:chunked 1Mbyte Upload結果

ohtsu@unix:~/tmp/post_test$ curl -v -H "Expect:" localhost:3000 -X POST --header "Transfer-Encoding: chunked" -F 'file=@1M.file'
* Rebuilt URL to: localhost:3000/
* Adding handle: conn: 0x105eb70
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x105eb70) send_pipe: 1, recv_pipe: 0
* About to connect() to localhost port 3000 (#0)
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 3000 (#0)
> POST / HTTP/1.1
> User-Agent: curl/7.32.0
> Host: localhost:3000
> Accept: */*
> Transfer-Encoding: chunked
> Content-Type: multipart/form-data; boundary=------------------------ec2042c3f7544c3b
>
< HTTP/1.1 204 No Content
< X-Powered-By: Express
< Date: Tue, 19 Nov 2013 04:51:08 GMT
< Connection: keep-alive
<
* Connection #0 to host localhost left intact

Transfer-Encoding:chunked 3Mbyte Upload結果

ohtsu@unix:~/tmp/post_test$ curl -v -H "Expect:" localhost:3000 -X POST --header "Transfer-Encoding: chunked" -F 'file=@3M.file'
* Rebuilt URL to: localhost:3000/
* Adding handle: conn: 0x120cb70
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x120cb70) send_pipe: 1, recv_pipe: 0
* About to connect() to localhost port 3000 (#0)
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 3000 (#0)
> POST / HTTP/1.1
> User-Agent: curl/7.32.0
> Host: localhost:3000
> Accept: */*
> Transfer-Encoding: chunked
> Content-Type: multipart/form-data; boundary=------------------------ab0b6ffea31f16e0
>
< HTTP/1.1 413 Request Entity Too Large
< X-Powered-By: Express
< Content-Type: text/plain
< Content-Length: 24
< Date: Tue, 19 Nov 2013 04:51:15 GMT
< Connection: keep-alive
<
* Connection #0 to host localhost left intact
Request Entity Too Large
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment