Skip to content

[HttpFoundation] Add Url and UrlParser #53346

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

Closed
wants to merge 1 commit into from

Conversation

alexandre-daubois
Copy link
Member

@alexandre-daubois alexandre-daubois commented Jan 2, 2024

Q A
Branch? 7.1
Bug fix? no
New feature? yes
Deprecations? no
Issues -
License MIT

This PR #53320 raised a problem in the codebase. Each place in the code where a DSN is parsed has its own implemented logic.

This led to various consistency issues: variable names differing from one place to another but having the same meaning, different behavior (some places decode HTML characters in URLs while others don't), work done "twice"... And of course, if a bug is detected somewhere, you have to check that it's not present everywhere (as must have been done with the PR mentioned above).

@OskarStark and @nicolas-grekas raised that there could be some place for something that unifies the work of DSN parsing which is of course always the same: parse the URL, decode the auth part with special chars, check a scheme is present, check the host is optionally present also.

Here is a first take on this. I created the logic in HttpFoundation, because why not, but I don't think this is the best place. However, we don't have any idea on where to put this as you can see in the comments of the linked PR 😄 I'm even sure that this is not the right place because, to me, add HttpFoundation as a dependency for this DSN parser feels weird.

A new component might be the solution, but it seems it was already discussed in the past and it was rejected (note that I couldn't find info about this, so if you were part of the discussion, feel free to link some issue or PR, thanks!).

This PR will give you an idea of what could be possible. I already leveraged this new mechanism in DI, Notifier, Mailer and Translation so you can see this in action. Of course, if this get accepted, the next step will be to leverage this in the Cache component mainly.

Things to discuss:

  • What are your thoughts on the API?
  • Where should we put this (new component, in an existing component, something else)?
  • Which additional feature should be bundled in Parser or Parameters?

/**
* @author Alexandre Daubois <alex.daubois@gmail.com>
*/
final class Parameters implements \Stringable
Copy link
Contributor

Choose a reason for hiding this comment

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

I would still name this àI would name this class Dsn`

@@ -92,17 +92,17 @@ public static function invalidDsnProvider(): iterable
{
yield [
'some://',
'The mailer DSN is invalid.',
'The "some://" DSN is invalid.',
Copy link
Contributor

Choose a reason for hiding this comment

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

Exposing the DSN here means it could leak sensitive data to a log file

@xabbuh
Copy link
Member

xabbuh commented Jan 2, 2024

see #32546 for a related discussion

@Nyholm
Copy link
Member

Nyholm commented Jan 2, 2024

Here is a link to a PR I made to try introduce a DSN component.
#36999

Symfony is all about following official standards. There is no standard for DSN (believe it or not). That is why it might be hard to push for a dedicated DSN component.

@nicolas-grekas
Copy link
Member

💯 That's why I wrote we might need a URL parser, not a DSN parser ;)

@alexandre-daubois
Copy link
Member Author

Alright I see the distinction. A bit of renaming is needed here. An URL parser could belong to HttpFoundation, as it already has some "UrlHelper".

@OskarStark
Copy link
Contributor

Symfony is all about following official standards. There is no standard for DSN (believe it or not). That is why it might be hard to push for a dedicated DSN component.

I understand, but we created our own standard of DSN in the Symfony world, which is spread across different components

@nicolas-grekas
Copy link
Member

we created our own standard of DSN in the Symfony world

That's not the case, each DSN in Symfony is potentially adhoc for the components that need one. There are already differences that are hard to abstract.

@Nyholm
Copy link
Member

Nyholm commented Jan 2, 2024

Symfony is all about following official standards. There is no standard for DSN (believe it or not). That is why it might be hard to push for a dedicated DSN component.

I understand, but we created our own standard of DSN in the Symfony world, which is spread across different components

Yes, that work has been implementation driven. I looked at how Symfony is using DSN and I created a specification for it. But making it a dedicated component says more "This is how Symfony think DSN should work". If we are just implementing DSN in various other components means we can eat the cake and have it too (ie don't agree on a standard but use DSN as we like).

Im obviously not against a DSN component or let a official DSN parser be part of HTTPFoundation, a new URI component. Im just trying to give some background or a TLDR for #36999 and #32546.

@alexandre-daubois
Copy link
Member Author

alexandre-daubois commented Jan 2, 2024

There are already differences that are hard to abstract.

Would you have an example? From what I saw during the rawurldecode URL, "everything" seems pretty aligned. Isn't the differences something that could be solved with some good polymorphism?

Im just trying to give some background or a TLDR

Thank you for that! 🙏

@Nyholm
Copy link
Member

Nyholm commented Jan 2, 2024

Would you have an example?

It is mostly the "function" part. Some components supports DSN like:

failover(dummy://a dummy://a)
failover(dummy://a,dummy://a)
failover:(dummy://a,dummy://a)
roundrobin(dummy://a failover(dummy://b dummy://a) dummy://b)

@alexandre-daubois
Copy link
Member Author

Just a quick thought but shouldn't we just use Tobias' package in the framework?

@alexandre-daubois alexandre-daubois changed the title [HttpFoundation] Add Dsn\Parser and Dsn\Parameters [HttpFoundation] Add Url and UrlParser Jan 2, 2024

class InvalidUrlException extends \InvalidArgumentException
{
public function __construct(string $dsn)
Copy link
Member

Choose a reason for hiding this comment

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

string $url ?

Copy link
Contributor

Choose a reason for hiding this comment

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

parameter can be removed IMHO

$dsn = $this->scheme.'://';

if ($this->isAuthenticated()) {
$dsn .= rawurlencode($this->user).':'.rawurlencode($this->pass).'@';
Copy link
Member

Choose a reason for hiding this comment

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

Will throw if one of this->user or this->pass is null, as rawurlencode() requires a string

Copy link
Member Author

Choose a reason for hiding this comment

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

Good catch 👍

public function __construct(
public string $scheme,
public ?string $user = null,
public ?string $pass = null,
Copy link
Member

Choose a reason for hiding this comment

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

Could we use password 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.

We could, but this would make impossible to do the following:

$url = new Url(...parse_url($url));

This is why I kept pass here

Copy link
Member

Choose a reason for hiding this comment

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

the goal of the new code should be to completely replace using parse_url, so this argument is void sorry. (parse_url is broken)

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh yes, of course 🤦 Updated accordingly

@welcoMattic
Copy link
Member

Is HttpFoundation the best place for such a parser? It will be used on Notifier, Translation, etc, in not necessarily HTTP request related context. I'm just back from holidays, maybe the topic has already been discussed elsewhere, but why not creating a small component named UrlParser?

@xabbuh xabbuh modified the milestones: 7.1, 7.2 May 15, 2024
@alexandre-daubois
Copy link
Member Author

Closed in favor of symfony/polyfill#498

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.

8 participants