How to properly cancel a file uploading request?

3,149 views
Skip to first unread message

Mophy Xiong

unread,
Feb 6, 2012, 12:16:28 AM2/6/12
to nodejs
Hi all,

We are writing a file uploading handler, by using formidable. Since
the file could be large, say 50M, we want to cancel the uploading
request if some necessary fields are missing or user quota exceeded,
so user do not need to wait until the file is completely uploaded to
see the response, and save our server from processing the unnecessary
uploading request.

It works just fine. By using req.client.destroy() or
res.connection.destroy(), the browser stops uploading immediately.

Until we put it behind a reverse proxy nginx. The nginx server will
firstly buffer the whole uploading body before it passes the control
to our uploading handler, so we don't have a chance to cancel the
uploading before it is completely uploaded.

Then we use node-http-proxy to replace the nginx server, which will
not buffer the request automatically.

But after we cancel the request in the uploading handler, the reverse
proxy node-http-proxy server will not do the same to the actual
client, which means the browser is still busy uploading. Then we add a
proxyError listener to the proxy, like this:

server.proxy.on('proxyError', function(err, req, res){
console.log('proxyError:');
console.dir(err);
if (err.code === 'ECONNRESET'){
res.connection.destroy();
}
});

Sometimes, this will success, if the err is { [Error: socket hang up]
code: 'ECONNRESET' }, the connection is successfully reset, and the
browser stops uploading right away. But sometime not, if the err is
{ [Error: write ECONNRESET] code: 'ECONNRESET', errno: 'ECONNRESET',
syscall: 'write' }, the res.connection.destroy() will just issue
another proxyError: { [Error: write EPIPE] code: 'EPIPE', errno:
'EPIPE', syscall: 'write' }, and the browser continues it's uploading
request.

Are we doing something wrong here?

Any suggestion is appreciated, thanks in advance.

Regards,
Mophy

Mophy Xiong

unread,
Feb 6, 2012, 10:03:17 AM2/6/12
to nodejs
Update:

After changing the following line:

if (err.code === 'ECONNRESET'){

to:

if (err.code === 'ECONNRESET' || err.code === 'EPIPE'){

We do can always cancel the request now. But we don't know if this
will cause any potential problems, like file/device handle/id problem
or any other OS level problems. So, if you can figure it out, please
let us know.

In another hand, we found after we canceled the uploading request,
there will be 1 or 2 or 3 segment files lay in the uploading
directory. And this is not from the reverse proxy, 'cause they will
show up even if we access the upload handler directly. For example,
after we canceled the uploading abc.7z (of 10M size), there will be
_random_name_a.7z, _random_name_b.7z in the uploading directory (yes,
we did emptied this directory before uploading). Each segment file may
be 32K or 64K size. Dose this means we didn't cancel the request
gracefully or something else?

Thanks in advance.


Regards,
Mophy

AJ ONeal

unread,
Feb 6, 2012, 12:52:19 PM2/6/12
to nod...@googlegroups.com
How about

    req.pause()
    res.status = 400;
    res.end('upload limit exceeded');

That will stop the data from coming in and the client may stay connected despite your response, but should eventually timeout in a harmless fashion.

AJ ONeal


--
Job Board: http://jobs.nodejs.org/
Posting guidelines: https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
You received this message because you are subscribed to the Google
Groups "nodejs" group.
To post to this group, send email to nod...@googlegroups.com
To unsubscribe from this group, send email to
nodejs+un...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/nodejs?hl=en?hl=en

Mophy Xiong

unread,
Feb 6, 2012, 9:54:36 PM2/6/12
to nodejs
Hi AJ,

Thank you for your reply. But it seems that doesn't stop the uploading
at all. The server continues getting the formidable progress event,
and the browser is still uploading, and the 'upload limit exceeded'
message is shown after the file is completely uploaded.

Regards,
Mophy

Mophy Xiong

unread,
Feb 7, 2012, 12:11:43 AM2/7/12
to nodejs
Hi AJ,

It seems req.pause() is a right way to do this. The reason it didn't
work well for our situation is a bug in node v0.6.x, according to this
post: http://groups.google.com/group/nodejs/t/a7386d38ee9e3d9d

Thank you.

Regards,
Mophy

Sandro Pasquali

unread,
Mar 16, 2012, 4:45:40 PM3/16/12
to nod...@googlegroups.com
This should actually terminate the connection:

request.abort();

I've also experimented with:

request.connection.destroy();
Reply all
Reply to author
Forward
0 new messages