-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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
[6.5] Fix various intl icu issues #2626
Conversation
Rolled this to production, not getting the deprecation notice anymore. |
+1 for getting this merged and released! |
Is symfony/polyfill#262 related? |
Hmmm, not really. There were issues with the older version of the polyfill too. |
Still getting 'IDN conversion failed' on all Guzzle Client requests, unless I specifically set 'idn_conversion=>false' Now using 1.17.0 of symfony/polyfill-intl-idn, and latest Guzzle 6.5.3 Guzzle 6.5.1 fixed this issue so I was able to drop 'idn_conversion=>false', but now the problem is back and I don't know why. Upping to 6.5.3 didn't cause this regression I don't think, but the problem seems to be there whether I'm using 1.15, 1.16 or 1.17 of symfony/polyfill-intl-idn :( |
You haven't tried applying this PR though... |
This will fix the issue for you. |
@GrahamCampbell Waiting for it to be in a release ... I tend to be happier to leave work-arounds in my code (like ['idn_conversion' => false]) than have forked/bodged-in-vendor-dir versions of dependencies. |
The only way for this PR to make it into a release is if people (like yourself) to test it so we know if it works. |
@GrahamCampbell I would love to be able to help by directly testing the change .. but unfortunately the only environment in which I'm experiencing the issue is in production (which is CentOS 6 / ICU 4.2.1 / cPanel WHM / PHP 7.3) .. whereas in my local dev environment (MAMP 5.7, PHP 7.3, macOS Catalina, ICU 56.1) there's no problem at all. So the only thing I can do (so production isn't broken), after researching the issue, is to set I would love to be able to help more, but my production environment is very busy running a constantly-used API + app, and is using Guzzle to handle all communication with external services and APIs. I understand that I could somehow perhaps deploy the fixed branch into production to test it, but that's a bit out of my league re: composer skills. Anyone got a link to a simple guide on how to do this? What would help (as much of the detail of this IDN/ICU stuff is way over my head) .. would be to have a clear idea of how somewhere between guzzle 6.5.1 and 6.5.3, and/or symfony/polyfill-intl-idn 1.15.0 to 1.16.0 .. the 'IDN conversion failed' error (which had gone away) .. has returned ? |
@GrahamCampbell Can you advise on how I could temporarily put your |
Like this? https://stackoverflow.com/questions/13498519/how-to-require-a-fork-with-composer |
@GrahamCampbell I can confirm this FIXES the problem for me, after testing in production..
WHM/cPanel (latest on 'release' channel)
composer.json file:
|
Yeh. Great. Thanks for confirming. I think this PR is good to be merged now. I'll contact the Guzzle core team. |
return \idn_to_ascii($domain, $options, INTL_IDNA_VARIANT_UTS46, $info); | ||
} | ||
|
||
return Idn::idn_to_ascii($domain, $options, Idn::INTL_IDNA_VARIANT_UTS46, $info); |
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.
Can this skip using the polyfill class directly? It's marked internal and it shouldn't be used.
If not, why did you do it this way?
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 we need to be able to call the polyfill even if the original extension is installed to work around the extension using a too old version of the C library. Symfony doesn't have a way for us to do this, other to call code that is formally internal.
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.
And this commit (included in polyfill-intl-idn 1.17 release) totally stops Guzzle doing anything other than calling the class method directly now..
symfony/polyfill-intl-idn@3bff59e
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.
...which to me suggests it should in fact be polyfill-intl-idn which should be verifying whether the ICU version available on the host machine is usable, or if the polyfill should be used instead, and it not be left to Guzzle to be looking at this and deciding for itself (therefore 'breaking the rules' by using code marked internal directly) .. ?
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.
@jonnott not possible. Userland implementations cannot replace functions defined by PHP.
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.
Oh well, looks like this PR is the best solution we have then.
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.
@jonnott this commit in the polyfill fixes detecting wrongly that INTL_IDNA_VARIANT_UTS46
is supported by idn_to_ascii
. It does not change the fact that idn_to_ascii
is defined by the extension when defined (and so the polyfill could not define it).
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 we need to be able to call the polyfill even if the original extension is installed to work around the extension using a too old version of the C library. Symfony doesn't have a way for us to do this, other to call code that is formally internal.
I wonder if it would be best to remove the polyfill. Library users that see a deprecation can set idn_conversion
to false and use their own custom solutions with a middleware or something like that.
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.
That's not always possible. For me, the trigger on the deprecation notice came from a third party library that uses yet another library which is instantiating its own Guzzle\Client
instance without any sane way for me to reach it to add middleware or set the idn_conversion
configuration.
return $domain; | ||
} | ||
|
||
if (\extension_loaded('intl') && defined('INTL_IDNA_VARIANT_UTS46')) { |
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.
you should remove the extension_loaded
check. That way, if you have only the polyfill installed, you will still call idn_to_ascii
(from the polyfill) rather than the internal API.
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.
There will always be a case where using the polyfill directly will be needed, so anyway...
BUT it's very possible that ppl forced the polyfill to be NOT installed, by using a "replace" for "intl" in their composer.json.
This "if" should add a || !class_exists(Idn::class)
to safeguard against this.
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.
Hmm, if anyone has done this, we'd expect a fatal error. I think that would be fine, since it indicates the class doesn't exist, and anyone who has forced non-installation will know that that means.
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.
require ext-intl + replace symfony/polyfill-intl is going to be very common.
We recommend it when possible for other polyfilled extensions.
A fatal error would be totally WTF I think...
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.
Another option would be to copy the polyfill source code into guzzle I guess, and not require the package.
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.
interested in creating a reuseable package both the polyfill and guzzle could depend on
we're not :)
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.
There will always be a case where using the polyfill directly will be needed, so anyway...
but that case would be the pure legacy one (having ext-intl installed with a legacy ICU version). Currently, polyfill internals are also used for the non-legacy case of not having ext-intl.
And for that legacy case, I would also vote for using the variant 2003 rather than using the polyfill internals.
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.
To support something that dates back to 2011?
Not actually 2011. Some distros from 2019 ship with old versions of the icu library that don't have this constant. This is one of the points of this PR and the older PR this fixes.
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.
To support something that dates back to 2011?
Not actually 2011. Some distros from 2019 ship with old versions of the icu library that don't have this constant. This is one of the points of this PR and the older PR this fixes.
For example CentOS 6, which is still supported until 2020-11-30, has ICU 4.2.1.
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.
But do recent PHP versions trigger a deprecation for the variant 2003 even when it was compiled without support for the uts46 variant ? that looks weird to me.
return $domain; | ||
} | ||
|
||
if (\extension_loaded('intl') && defined('INTL_IDNA_VARIANT_UTS46')) { |
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.
There will always be a case where using the polyfill directly will be needed, so anyway...
BUT it's very possible that ppl forced the polyfill to be NOT installed, by using a "replace" for "intl" in their composer.json.
This "if" should add a || !class_exists(Idn::class)
to safeguard against this.
Hey, i confirm that with this fix i cannot reproduce issue anymore. It will be merged and released? Or there is another approach for this bug? |
Thank you for all reviews and confirming that this works. Im happy with this PR after some small changes. See: https://github.com/GrahamCampbell/guzzle/pull/1 |
Lock version to symfony/polyfill-intl-idn:1.17.0
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.
Thank you
@@ -23,7 +23,7 @@ | |||
"require": { | |||
"php": ">=5.5", | |||
"ext-json": "*", | |||
"symfony/polyfill-intl-idn": "^1.11", | |||
"symfony/polyfill-intl-idn": "1.17.0", |
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.
Sorry to chime in after merge: locking to a specific version of the polyfill effectively prevents installing any new(/old) versions ppl might want to use in their app. This is taking control away from users.
I'd recommend using ^1.17
.
I suppose this was done as a measure against using an @internal
class. But the "risk" this guards against is not strong enough to justify locking all users.
The bigger risk I mentioned in my review is someone using "replace": "symfony/polyfill-intl"
.
In order to guard from this risk, I'd recommend adding a class_exists(Idn::class)
check before using the class instead.
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.
We will allow more versions after they are released and we can confirm comparability. Just like someone would write 5.x interested of >=5, we have to bound our versions.
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.
In order to guard from this risk, I'd recommend adding a class_exists(Idn::class)
That is insufficient. What if the method is renamed, etc. No point in guessing everything possible. If someone has "replaced" the polyfill then this won't matter anyway.
This fixes the following issues: