Skip to content

Conversation

derrabus
Copy link
Member

@derrabus derrabus commented Mar 10, 2021

This bundle is an attempt to create a nicer and more seamless integration than the recipe previously provided.

Fixes symfony/recipes#909

Services

The bundle will provide the following services:

psr_http_message.http_foundation_factory

This is HttpFoundationFactory and allows us to convert PSR-7 messages into HttpFoundation objects. This service is always enabled and it's the only service that does not require any additional packages. An autowiring alias for Symfony\Bridge\PsrHttpMessage\HttpFoundationFactoryInterface is provided.

PSR-17 factories

  • psr_http_message.psr.request_factory
  • psr_http_message.psr.response_factory
  • psr_http_message.psr.server_request_factory
  • psr_http_message.psr.stream_factory
  • psr_http_message.psr.uploaded_file_factory
  • psr_http_message.psr.uri_factory

Those services require a PSR-17 implementation to be present. If nyholm/psr7 is installed, the factories are enabled automatically. Alternatively, the bundle can also configure laminas/laminas-diactoros.

Autowiring aliases for all PSR-17 interfaces are provided.

psr_http_message.psr_http_factory

This is PsrHttpFactory. It allows up to convert HttpFoundation objects into PSR-7 messages. The service is available if the PSR-17 factories have been enabled (because of the obvious dependency). Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface is registered for autowiring.

Message converters

PsrResponseListener and PsrServerRequestResolver have been added to the bridge in version 2.1.0. Enabling those allows us to write controllers that operate on PSR-7 messages instead of HttpFoundation. This functionality is disabled by default and can be enabled.

Configuration reference

psr_http_message:

    message_factories:
        enabled : true
        implementation: nyholm # alternatively: "diactoros"

    message_converters:
        enabled: false

    response_buffer: 16372 # Fine-tuning for HttpFoundationFactory

@derrabus derrabus force-pushed the improvement/bundle branch from a8f1fc1 to 17fd440 Compare March 10, 2021 18:08
@ajgarlag
Copy link

I wrote a drop-in replacement for PSR-7 functionality removed from sensio/framework-extra-bundle

You can see it at https://github.com/ajgarlag/psr-http-message-bundle

@derrabus derrabus force-pushed the improvement/bundle branch 3 times, most recently from 1481e6a to dd0aa2b Compare March 10, 2021 18:49
@derrabus derrabus force-pushed the improvement/bundle branch from dd0aa2b to 751081d Compare March 10, 2021 22:35
Copy link
Member

@Nyholm Nyholm left a comment

Choose a reason for hiding this comment

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

Im happy with this.

@ajgarlag, Is there any feature your bundle supports that should be added here?

@derrabus derrabus force-pushed the improvement/bundle branch 2 times, most recently from 71292a1 to 358ff66 Compare March 11, 2021 09:18
@ajgarlag
Copy link

@ajgarlag, Is there any feature your bundle supports that should be added here?

There are at least two things I miss in this bundle:

  1. Rely on any PSR-17 implementation. I would allow a third value in psr_http_message.message_factories.implementations that could be called custom. With this value, the developer must define the required PSR-17 factories in the container using FQCN as identifiers. The bundle should check that these services are available.
  2. Provide and document a smooth upgrade path for projects thar require PSR-7 support from sensio/framework-extra-bundle:<6.0 + symfony/psr-http-message-bridge:^1.1, to symfony/psr-http-message-bridge:^2.2

@Nyholm
Copy link
Member

Nyholm commented Mar 11, 2021

I agree that these things should be added to the bundle. Is that something you want to help adding?

Copy link
Member

@weaverryan weaverryan left a comment

Choose a reason for hiding this comment

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

Thanks for this!

$configuration = $this->getConfiguration($configs, $container);
$config = $this->processConfiguration($configuration, $configs);

$container->setParameter('psr_http_message.response_buffer', $config['response_buffer']);
Copy link
Member

Choose a reason for hiding this comment

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

Does this need to be a parameter? Or could we pass it directly into the psr_http_message.http_foundation_factory service?

public function load(array $configs, ContainerBuilder $container): void
{
$loader = new PhpFileLoader($container, new FileLocator(\dirname(__DIR__).'/Resources/config'));
$loader->load('http_foundation.php');
Copy link
Member

Choose a reason for hiding this comment

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

So if I'm reading things correctly, out of the box (with no config), the bundle would just give you a service for HttpFoundationFactory, correct? That seems to make sense :)

->set('psr_http_message.server_request_resolver', PsrServerRequestResolver::class)
->args([new Reference('psr_http_message.psr_http_factory')])
->tag('controller.argument_value_resolver')
;
Copy link
Member

Choose a reason for hiding this comment

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

Is it possible to enable these automatically (and then maybe allow them to be DISABALED)? I'm trying to avoid users almost ever needing the config file. The first could always be enabled (the service is available, is there a downside)? The second could be enabled if/once psr_http_message.psr_http_factory is present. I'm trying to give the user more, with less config. WDYT?

Copy link
Member

Choose a reason for hiding this comment

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

The downside is runtime overhead on the hotpath yes.

Copy link
Member

Choose a reason for hiding this comment

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

Ok, let's not do that then ;)

@derrabus
Copy link
Member Author

I've added a CI job that tests the bundle's behavior without any PSR-7 implementations. I think, the PR is ready now.

->alias(ServerRequestFactoryInterface::class, 'psr_http_message.psr.server_request_factory')
->alias(StreamFactoryInterface::class, 'psr_http_message.psr.stream_factory')
->alias(UploadedFileFactoryInterface::class, 'psr_http_message.psr.uploaded_file_factory')
->alias(UriFactoryInterface::class, 'psr_http_message.psr.uri_factory')
Copy link
Member

Choose a reason for hiding this comment

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

there is a soft conflict between these and https://github.com/symfony/recipes/blob/master/nyholm/psr7/1.0/config/packages/nyholm_psr7.yaml

should we remove the recipe for nyholm/psr7 in favor of this bundle?

Copy link
Member Author

Choose a reason for hiding this comment

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

I think we should.

Copy link
Member

Choose a reason for hiding this comment

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

I was about to send a PR, but then: ppl won't be able to add only one package to have working psr17 factories. If they install the bridge, they won't have the implementation. And if we they install the implementation and we remove the recipe, they won't have the aliases :(

Choose a reason for hiding this comment

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

Can you see derrabus#1? It's an attempt to support any PSR-17 implementation.

Copy link
Member Author

Choose a reason for hiding this comment

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

Then again, if we just leave everything as is, not much will break. The Nyholm recipe will steal the aliases, but they point to the same stateless classes anyway.

What we could do:

  • We could comment out the aliases in the Nyholm recipe and add a note that the developer should either un-comment them or install the bundle for a better integration.
  • Add a pack that depends on the bridge and the Nyholm implementation and remove the Nyholm recipe.

Copy link
Member Author

Choose a reason for hiding this comment

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

@ajgarlag Thank you! Let's merge this PR first and move your PR to this repo afterwards.

Copy link
Member

Choose a reason for hiding this comment

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

It'd like to give the pack approach a try before merging, because I'm not sure this bundle is the best approach, especially since we're still talking about a pack here...

Copy link
Member Author

Choose a reason for hiding this comment

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

Okay, go ahead.

Choose a reason for hiding this comment

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

@derrabus I could split my PR into two commits:

  1. Conditionally add PSR-17 aliases in a Compiler pass if not defined previously.
  2. Support any PSR-17 implementation.

I think that the first one could be included here. WDYT?

Copy link
Member Author

Choose a reason for hiding this comment

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

Let's wait for Nicolas first.

@nicolas-grekas
Copy link
Member

nicolas-grekas commented Mar 18, 2021

I'm been hesitating a lot here, and now I think we should go with the "pack + recipe" approach.
Unless we make nyholm/psr7 a required dependency, we cannot wire any implementation by default.
This kills the approach proposed in this PR to me.

There are alternatives / ways forward, eg removing the recipe bound to nyholm/psr7 and not binding any recipe to psr7-pack. Or create a separate psr7-bundle that requires nyholm/psr7+this-bridge. But I think these approaches have significant drawbacks compared to the "pack + recipe" approach.

See symfony/recipes#911 for what I think is enough to make all this work.

@nicolas-grekas
Copy link
Member

Closing in favor of symfony/recipes#911
Thanks @derrabus

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

Successfully merging this pull request may close these issues.

New symfony/psr-http-message-bridge recipe KO's out-of-the-box with sentry/symfony

7 participants