ostinelli / misultin

Misultin (pronounced mee-sool-téen) is an Erlang library for building fast lightweight HTTP(S) servers, which also supports websockets.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Error with file upload on slow network

cloudhead opened this issue · comments

I'm testing the file upload functionality with an intentionally crippled network, and getting some timeouts after long file uploads (> 1 min). Here's the setup:

Cap network bandwidth to 600Kbit/s and add 50ms latency:

 sudo ipfw pipe 1 config bw 600Kbit/s delay 50ms

 sudo ipfw add 1 pipe 1 src-port 8080
 sudo ipfw add 2 pipe 1 dst-port 8080

Here's the error I get after about 1.5 minutes of a 900K file:

18:46:41.773 [error]    module: misultin_http
        line: 392
error reading body: timeout

18:46:41.777 [error]    module: misultin_http
        line: 363
request timeout, sending error

Misultin version is 0.9-dev (current master I think)

Any ideas why it's timing out? I'm tracking the file progress, and it seems like it's being uploaded...

Note: everything seems to work fine without the artificial network delay, and everything but file uploads work fine with the delay. I'm just worried this could happen when the site is live.

hi,

have you tried starting misultin with the recv_timeout option? This allows you to specify the maximum allowed timeout, and it defaults to 30000 ms.

you may consider increasing this timeout, or even setting it to infinity (definitely not recommended).

also: how are you trying to upload the file? chunked encoding?

please let me know and we can go on from there.

r.

I haven't tried, are you saying it considers the file upload as a single operation? In that case it'll timeout if the file takes longer than 30s to upload, even if it has received data 1 second ago, correct?

I will try now with infinity, just to see if that's the issue.

I'm uploading the file via a form with multipart/form-data, but asynchronously, using FormData—the initial request looks like this:

PUT http://127.0.0.1:8080/upload HTTP/1.1
Origin: http://127.0.0.1:8080
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.63 Safari/535.7
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryghgPGhJfvWWxzxsj
Accept: text/plain
Referer: http://127.0.0.1:8080/

------WebKitFormBoundaryghgPGhJfvWWxzxsj
Content-Disposition: form-data; name="file"; filename="artwork.tiff"
Content-Type: image/tiff


------WebKitFormBoundaryghgPGhJfvWWxzxsj--

I'm not aware of the possibility of using chunked transfer-encoding when doing file uploads.

Will post back soon.

Ok, so setting recv_timeout to 600000 solved the issue (infinity doesn't seem to work, it asks for an integer timeout).

It seems like it's a compromise though, because it is receiving data, but the timeout is not considering that—it views it as an "atomic" request/response, instead of a stream. Unless I'm mistaken, it should timeout only if it hasn't received any data in recv_timeout ms.

Am I missing anything? anything we can do?

Hi,

sorry for the infinity suggestion: I actually had this disabled some time ago and it now only accepts integers, which I believed (and still do) to be the sane and safe approach.

The timeout is defined as per the gen_tpc:recv/3 function specs. The code in misultin that is issuing the timeout is here.

I'd believe too that Timeout relates to the maximum allowed time for a socket to not receive any data, however just in case I've posted a question to the Erlang Questions mailing list.

FYI, you can do chunked transfer-encoding file upload in misultin, server-side example here.

r.

Hmm I see.. but are you sure it isn't an internal erlang message which is timing out in this case? Like here: https://github.com/ostinelli/misultin/blob/master/src/misultin_http.erl#L202 for example?

I see how I can do chunked-encoding server-side, but my understanding is that it can only be used for http responses, not requests.. is that not correct? Or do you mean a chunked response might help here?

Yes. The {active, once} parameter is used at that point, plus the log you posted is pretty self-explanatory to where this is happening.

I've received a reply in the mailing list. This is very interesting, and I'll provide a patch asap. I'll ping you to test it with your configuration too, and see if that solves it.

As far as your other question, the example I've linked demonstrates how to read chunked encoding from requests. This is useful to provide upload streaming functionalities, for instance.

r.

Very interesting indeed, it seems like with that fine-grained control, there can be a solution! I'll be awaiting your patch.

About the chunked-encoding, the thing is I don't think it is possible to force it from the browser.

I've tested some patches. these solve this issue, however introduce unnecessary complexity / slowness for 'normal' connections.

currently the only solution i can see is increase the timeout, which is an option already provided. if you have any input do not hesitate.

thank you for this.

misultin has been discontinued, my reasons here.

r.