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

Multipart handling #13

Merged
merged 6 commits into from
Aug 10, 2015
Merged

Multipart handling #13

merged 6 commits into from
Aug 10, 2015

Conversation

onigoetz
Copy link
Contributor

@onigoetz onigoetz commented Oct 9, 2014

Hello,

I added basic support for multipart for files and POST requests

I also wrote the unit tests for this part and improved the existing ones.

One thing that could be done better is that now, it waits for the whole body before it parses it, we could implement a system where it feeds the content to the parser and the files are created on the fly and we don't use the whole memory for file uploads.

Future change will be made and the class will become a body parser as well
- fixed the header overflow
- added the body to the Request
- parse POST form the body content or as multipart/form-data
- handle file uploads
- use Content-Length to know when the content arrived
@onigoetz
Copy link
Contributor Author

Hi @cboden @igorw,
I see that the split is now done, are you interested in my pull request for multipart handling in the http part ?

@cboden
Copy link
Member

cboden commented Dec 11, 2014

Hi @onigoetz

Thank you very much for your hard work and contribution. This is absolutely something we want! My apologies it's taking so long, this PR is coming up on my todo list of things to review.

$content = ltrim($content, "\r\n");

$path = tempnam(sys_get_temp_dir(), "php");
$err = file_put_contents($path, $content);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Filesystem interactions block. We can't have these in the library.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for your input. but then how could we handle file uploads ?
Keeping them in memory is too dangerous because of the size these uploads could be.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Following the Single Responsibility Principle the library should be all things handling and serving HTTP. How to transfer a file is defined in the HTTP specification but not how to save it. I think at this point instead of writing to a file we should provide indirection for the user to handle the file in chunks.

For example if I were implementing this I think I would want a callback to receive a file in chunks and as I received each chunk I would pipe it to a file using react/filesystem or perhaps pipe it to a worker script that writes to disk (but blocks).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for the idea, I'll figure something out and update the pull request.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Imho it would be better when you use streams and pass those along. That way the developer can decide what to do with the contents of the stream.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You think one stream per fileupload or the raw stream ?

I'll look how I can do that, I'm not a stream expert

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A stream per fileupload. Ping me on IRC or on twitter if you have questions about that. Happy to help :).

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have suggestion about how to do that:

  • add one more argument (callable or factory) for handling file uploads to server constructor
  • then when it comes to file handling we just call callable or factory (with arguments like file name, mime type) and pass everything to method of object it returned (if there was no callable or factory - just ignore uploaded file, it is too expensive to store it in memory)
  • after whole request parsed we'll have access to array with all objects we've created for uploaded files

What you think about such approach?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your ideas, I will try to make it this week.

@cboden cboden mentioned this pull request Jan 25, 2015
# By Michael Arenzon
# Via Chris Boden (1) and Michael Arenzon (1)
* 'master' of github.com:reactphp/http:
  just for better ide completion
@WyriHaximus
Copy link
Member

@onigoetz after reading you're message here reactphp/reactphp#3 (comment) want me to look into that for you and make a PR on your PR?

@onigoetz
Copy link
Contributor Author

@WyriHaximus yes I would be very happy if you can help on the matter.

@WyriHaximus
Copy link
Member

@onigoetz I'll look into it tonight or tomorrow 👍

@HonzaMac
Copy link

HonzaMac commented Jul 1, 2015

Any progress on that?

@onigoetz
Copy link
Contributor Author

onigoetz commented Jul 1, 2015

None one my part, @WyriHaximus were you able to take a look ?

@WyriHaximus
Copy link
Member

WyriHaximus commented Jul 2, 2015 via email

onigoetz added 3 commits July 28, 2015 21:50
* source/master:
  Removed a blank as pointed out in this comment: 10af1f5#commitcomment-11894795
  Added 0.4.1
  Use new Guzzle PSR7 parser
  Test against PHP7
  Adding Code Climate badge to readme

# Conflicts:
#	src/RequestHeaderParser.php
@onigoetz
Copy link
Contributor Author

Hi guys, I updated my fork to be up to date with all the changes on the master branch.

I also changed the logic to not store the file upload in temp files, but keep them in a stream.

I think this PR could be merged as-is and another pull-request could finish the work I started. What do you think ? As things are working pretty well on the multipart handling part.

@WyriHaximus
Copy link
Member

@onigoetz cheers looks good, will have a go with it again this weekend. My apologies for not getting back to you last time. I've looked into converting it into a stream streaming files and that looked harder then expected at the time. Going to either a special stream/buffer for it and do a follow up PR getting that in.

This next bit is a braindump from a previous chat on IRC about it. The idea was to emit events on files found in the stream and also on multipart bits.

Since steaming support also has to be done I can include the above bit in that PR as well :).

WyriHaximus added a commit that referenced this pull request Aug 10, 2015
@WyriHaximus WyriHaximus merged commit b36fb25 into reactphp:master Aug 10, 2015
@WyriHaximus
Copy link
Member

I'll follow this up shortly with another PR before tagging it. Thanks for the work 👍

@nazar-pc
Copy link

Can't believe it was finally merged) Yay!

@onigoetz
Copy link
Contributor Author

👍 awesome !

@WyriHaximus
Copy link
Member

@onigoetz will try to dedicate as mush OSS time as I can on the follow up. Will comment here when the initial WIP PR is up

@HonzaMac
Copy link

Awesome! Cant believe tooo 👍

@clue
Copy link
Member

clue commented Sep 4, 2015

As much as I'd love to see multipart handling in here, I have to admit I'm not a big fan of the current implementation.

I think it's important to consider that HTTP request bodies can be of arbitrary sizes. While a common form submission only results in a few (kilo)bytes of data, it's quite common to use HTTP-based APIs to transmit multi-megabytes of data. The same applies to uploading files via HTML forms or using CLI-based tools to trigger similar HTTP requests.

Admittedly, a streaming approach where only small chunks are kept in memory is probably slightly more complicated to implement and likely more difficult to consume from a user perspective.

FWIW, a streaming approach could probably look somewhat similar to a TAR-file decoder which emits an event for each part and then only streams its contents. I have to admit I hate posting links to my own libraries, but perhaps https://github.com/clue/php-tar-react could be a good start here?

Any considerations?

@WyriHaximus
Copy link
Member

@clue working on a streaming implementation inspired by clue/php-tar-react 👍

@clue
Copy link
Member

clue commented Sep 4, 2015

@WyriHaximus Awesome, keep me posted! Would love to take a look at this eventually

@WyriHaximus
Copy link
Member

@clue will do, gained some good experience with out-of-the-box streams in https://github.com/reactphp/filesystem so it should be a matter get getting into the flow

@onigoetz
Copy link
Contributor Author

onigoetz commented Sep 4, 2015

I admit my first implementation was very naive and I wanted to make a streaming implementation after a first working version, sadly I did not have time to do so.

"""


Stéphane Goetz
Développeur Web

http://www.onigoetz.ch

Mobile : +41 79/824.77.68
Mail : [email protected]

On 4 sept. 2015 20:19 +0200, Cees-Jan [email protected], wrote:

@clue(https://github.com/clue)will do, gained some good experience with out-of-the-box streams inhttps://github.com/reactphp/filesystemso it should be a matter get getting into the flow


Reply to this email directly orview it on GitHub(#13 (comment)).

@WyriHaximus WyriHaximus mentioned this pull request Oct 1, 2015
8 tasks
@WyriHaximus
Copy link
Member

#41 is the follow up PR, feedback is welcome

clue added a commit to clue-labs/http that referenced this pull request Aug 9, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants