From 3aded4a35f50dfa57bf5587696fabd99dbfc0651 Mon Sep 17 00:00:00 2001 From: Mponos George Date: Sun, 8 Dec 2019 14:44:02 +0200 Subject: [PATCH] Add IDN support for redirects also --- src/RedirectMiddleware.php | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/RedirectMiddleware.php b/src/RedirectMiddleware.php index 5a0edd572..9d5ad6a62 100644 --- a/src/RedirectMiddleware.php +++ b/src/RedirectMiddleware.php @@ -2,6 +2,7 @@ namespace GuzzleHttp; use GuzzleHttp\Exception\BadResponseException; +use GuzzleHttp\Exception\InvalidArgumentException; use GuzzleHttp\Exception\TooManyRedirectsException; use GuzzleHttp\Promise\PromiseInterface; use GuzzleHttp\Psr7; @@ -190,7 +191,41 @@ public function modifyRequest( $modify['body'] = ''; } - $modify['uri'] = $this->redirectUri($request, $response, $protocols); + $uri = $this->redirectUri($request, $response, $protocols); + + if ($uri->getHost() && isset($options['idn_conversion']) && ($options['idn_conversion'] !== false)) { + $idnOptions = ($options['idn_conversion'] === true) ? IDNA_DEFAULT : $options['idn_conversion']; + + $asciiHost = idn_to_ascii($uri->getHost(), $idnOptions, INTL_IDNA_VARIANT_UTS46, $info); + if ($asciiHost === false) { + $errorBitSet = isset($info['errors']) ? $info['errors'] : 0; + + $errorConstants = array_filter(array_keys(get_defined_constants()), function ($name) { + return substr($name, 0, 11) === 'IDNA_ERROR_'; + }); + + $errors = []; + foreach ($errorConstants as $errorConstant) { + if ($errorBitSet & constant($errorConstant)) { + $errors[] = $errorConstant; + } + } + + $errorMessage = 'IDN conversion failed'; + if ($errors) { + $errorMessage .= ' (errors: ' . implode(', ', $errors) . ')'; + } + + throw new InvalidArgumentException($errorMessage); + } else { + if ($uri->getHost() !== $asciiHost) { + // Replace URI only if the ASCII version is different + $uri = $uri->withHost($asciiHost); + } + } + } + + $modify['uri'] = $uri; Psr7\rewind_body($request); // Add the Referer header if it is told to do so and only