Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Large file uploads #63

Closed
mme opened this issue Apr 16, 2013 · 12 comments
Closed

Large file uploads #63

mme opened this issue Apr 16, 2013 · 12 comments

Comments

@mme
Copy link

mme commented Apr 16, 2013

Is it possible to handle large file uploads in middleware, i.e. stream the body to disk instead of keeping it in memory ?

@knutin
Copy link
Owner

knutin commented Apr 16, 2013

There is currently no streaming or chunked support for receiving requests, only chunked transfer responses.

The reason is to make handlers and middlewares semantically simpler. When the handler is called, it knows that whatever is inside of the request will not change. The return value from the handler is what is returned to the user. This avoids many of the problems found in Cowboy, Misultin, Mochiweb and Yaws. For example every time you look at a part of the request it might have side effects like talking to a port or asking a process for some data. Whenever you send a response, great care needs to be taken that you don't send the body before the headers, or the body twice, etc, which again might be implemented with messaging a port or another process.

Elli makes a tough choice to have simple semantics of writing a handler. The handler can be referentially transparent and without side-effects, at least as far as dealing with the request and response is concerned.

With that said, maybe there would be a way of allowing people to venture into crazy land if they so wish. I have been playing around with handing over the socket to the handler after receiving the headers. The handler can then decide what behaviour fits this particular request best. Maybe the handler wants to receive the body in multiple chunks, stream it to disk, implement websockets, etc. Specifically, I'm thinking maybe there would be an "init" function called inside the handler which gets the request without the body and can signal the behaviour wanted by returning a value. If the function is not defined, the default of "rack-style" is used.

I know of some more users that has been wishing for the same feature which would allow them to implement websockets. Do you have any more use cases to add to the list?

@mme
Copy link
Author

mme commented Apr 16, 2013

I can't think of any case except file uploads and websockets.

If it's possible to delegate this functionality to middleware while keeping the core simple, i think it would make a great addition to Elli - in the spirit of "simple things should be simple, complex things should be possible"...

For my use case, I can upload large files directly to S3 and handle the rest with Elli.

@knutin
Copy link
Owner

knutin commented Apr 16, 2013

I will give implementing it a go soon. Then we can see what it would look like.

@mme
Copy link
Author

mme commented Apr 16, 2013

That's great.

I would try to implement the disk streaming when you have done an init callback.

@knutin
Copy link
Owner

knutin commented Apr 17, 2013

Check out the "handover" branch. If you export an init/2 function in your handler and return {ok, handover}, Elli will call your handle/2 before receiving the body. You can then receive the body and send the response on your own using elli_http:send_response/2. The return value should be {close | keep_alive, Buffer :: binary()} where Buffer is any data belonging to the next request, otherwise empty binary.

@mme
Copy link
Author

mme commented Apr 25, 2013

I'll try the handover approach over the weekend and give you feedback. I did some work on multipart parsing - https://github.com/mme/erlmultipart

@mme
Copy link
Author

mme commented Apr 27, 2013

This is a working sample that streams the upload to disk: https://github.com/mme/elli_upload_sample

Is it possible to go back to the normal handle flow after body parsing ?

@knutin
Copy link
Owner

knutin commented Jun 15, 2013

Hey, sorry for not getting back to you. I started a new job and it has been a bit crazy.. :-)

This stuff looks really cool. I'll try to clean up the handover branch a bit soon and merge it to master. I will also give a go at going back to the normal handle flow.

@mmzeeman
Copy link
Contributor

Here is elli_websocket, also build on the handover branch. https://github.com/mmzeeman/elli_websocket

@tsloughter
Copy link
Contributor

Any chance of this being included? elli would be a nice successor to mochiweb and this seems like the main missing feature.

@rgrinberg
Copy link

Isn't this already included? Seems like handover functionality is in master https://github.com/knutin/elli/blob/master/src/elli_example_callback_handover.erl

@knutin
Copy link
Owner

knutin commented May 3, 2016

Yup, it's been there a while even, just forgot to close this ticket. (:

@knutin knutin closed this as completed May 3, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants