-
-
Notifications
You must be signed in to change notification settings - Fork 57
Initial support #1
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
Conversation
dunglas
commented
May 21, 2015
Q | A |
---|---|
Bug fix? | no |
New feature? | yes |
BC breaks? | no |
Deprecations? | no |
Tests pass? | yes |
Fixed tickets | n/a |
License | MIT |
Doc PR | symfony/symfony-docs#5331 |
- Composer dependencies
- Interfaces
- Stub
- HttpFoundationFactory implementation
- DiactorosFactory implementation
- StreamedResponse
* | ||
* @author Kévin Dunglas <[email protected]> | ||
*/ | ||
interface HttpFoundationFactoryInterface |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure we need interfaces here (there is no reason to reimplement the conversion in a different way IMO). And I would rather name them converters than factories
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@stof I agree but it was to be consistent with the other side, and the other side needs an interface.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does it actually need one though ? If we want to make it usable with other PSR-7 implementation, we could just accept a constructor callable to instantiate the Request/Response rather than forcing to reimplement the whole conversion (which is not only about the constructor)
My idea was to have separate classes for the Request and the Response converters, because a typical use case will need to convert the Request one way and the Response the other way. |
The userland API I was thinking about was: public function myAction(Request $mySymfonyRequest)
{
$psr7Request = $this->get('http_message_factory')->createRequest($mySymfonyRequest);
$psr7Response = $somePsr7Middleware->execute($psr7Request)
return $this->get('http_foundation_factory')->createResponse($psr7Response);
} What do you think about it? |
As you can see, the |
@dunglas I don't think we will register them as services. Using them in a controller looks really weird. The use case is more for middleware compatibily IMO (a zend stragility middleware wrapping HttpKernel or an HttpKernel wrapping a zend diactoros server for instance). |
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function createUploadedFile(UploadedFile $symfonyUploadedFile) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this should be public
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't you think it can be useful in many cases to convert from Symfony to PSR UploadedFile and vice versa?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, we could make it public later if we get requests about it. But for now, I would keep it private until we get more feedback (increasing the visibility of a method is easy. Decreasing it is forbidden outside major versions, and it is still a pain for major versions if we want to provide an easy upgrade)
I was more thinking about having proxy classes. Having factories and services seems overkill here. The "converters" are going to be used at the edges anyway, not in your core code. |
@fabpot having proxy classes is possible for the HttpFoundation -> PSR-7 is possible (this is what https://github.com/Sam-Burns/psr7-symfony-httpfoundation started to do), but it is also a pain to ensure that we can never perform external mutation of the wrapped objects. |
And this library only implements the easy parts for now (uploaded files and the body stream are not yet adapted) |
Agree with @stof, creating proxies will be a huge pain IMO. The service was just an example. I'm thinking about a way to introduce progressively PSR-7 in the core of Symfony. What do you think about the following: Additionally to public function myAction(\Psr\Http\Message\ServerRequestInterface $psrRequest); We will only need to adapt the following snippet https://github.com/symfony/symfony/blob/2.7/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php#L115 to convert the Symfony Request to the PSR one using the factory. Similarly, it is possible to add methods returning instances of PSR It will improve drastically the interoperability of Symfony with other PSR-7 compliant libraries. |
@stof could you make a brain dump of what you had in mind to implement? :) |
@dunglas returning a PSR request from events would be a pain, because listeners are allowed to mutate the request, and we would then have to provide a way to set the updated PSR request in the event, which would then have to mutate the existing HttpFoundation Request. Too much trouble IMO. |
@jakzal My idea was 2 have 4 converter classes (Request/Response, both ways => 4 needed). |
@stof I've no strong opinion against splitting factories for request / response, lets do that if every one agree, but I cannot find the problem with the following: $httpFoundationFactory = new \Symfony\Bridge\PsrHttpMessage\Factory\HttpFoundationFactory();
$psrFactory = new \Symfony\Bridge\PsrHttpMessage\Factory\DiactorosFactory();
$response = new \Zend\Diactoros\Response();
$done = function($request, $reponse) {
$symfonyResponse = $httpFoundationFactory->createResponse($reponse);
// Do the something the Symfony way
};
$server = new \Zend\Diactoros\Server(
function ($psrFactory->createRequest($symfonyRequest), $response, $done) {
$response->getBody()->write("Hello world!"); },
$request,
$response
); |
Added cookies support. |
All issues raised by @stof (thank you!) should be fixed now. |
$request = new ServerRequest( | ||
$server, | ||
DiactorosRequestFactory::normalizeFiles($this->getFiles($symfonyRequest->files->all())), | ||
DiactorosRequestFactory::marshalUriFromServer($server, $headers), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not reusing $symfonyRequest->getRequestUri()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because Symfony sometimes generates bad URIs. For instance with the request I build in the test, the generated URL is http://:/
(because some $_SERVER parameters are missing).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like @stof's general idea - we should use as much information from Symfony's Request as possible, since it's already calculated there and I expect information to be the same. For example, what if the scheme is http
in Symfony's Request, but due to some x-forwarded-proto
differences (perhaps you don't have something a proxy trusted in Symfony's Request), Diactoros reads the untrusted x-forwarded-proto
and treats it as https
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not. So I'll fix the test with the correct $_SEVER keys but if we got some complaints about strange bugs here we should fix HttpFoundation directly.
}); | ||
|
||
$symfonyResponse->sendContent(); | ||
ob_end_clean(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This means that the streamed content will in fact be read into memory, correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because I use php://temp
, after 2Mo the data will be stored in a temporary file on disk.
|
Looks good to me. @dunglas Anything else before merging and releasing 0.1? |
Looks good to me too for this one. The last thing to do is deciding the strategy for cookie handling (copy/pasting BrowserKit, making BrowserKit a dependency or letting that as is but this can be done in a future version. I've made some tests today with the standard edition of Symfony 2.6 + SensioFrameworkExtraBundle master and it works well. |
Thank you @dunglas. |
v 0.1 is released now: https://packagist.org/packages/symfony/psr-http-message-bridge @dunglas Can you update the PR on the bundle? |
Done in fc8241c. Travis is running. |
Wow, congrats! This certainly exceeded my expectations in speed. 🍻 for @dunglas |
Congratulations @dunglas |
This PR was merged into the 2.7 branch. Discussion ---------- [PSR-7] Bridge documentation | Q | A | ------------- | --- | Doc fix? | no | New docs? | yes | Applies to | 2.7 symfony/psr-http-message-bridge#1 | Fixed tickets | n/a Documents the PSR-7 Bridge. As there was no previous doc for bridges, I created a structure but not sur if this is a good idea. Commits ------- 695fe21 [PSR-7] Bridge documentation