Jelajahi Sumber

Merge pull request #1032 from acelaya-forks/feature/twitter-validation

Feature/twitter validation
Alejandro Celaya 3 tahun lalu
induk
melakukan
5b93cf42b1

+ 1 - 0
CHANGELOG.md

@@ -19,6 +19,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com), and this
 
 ### Fixed
 * [#1024](https://github.com/shlinkio/shlink/issues/1024) Fixed migration that is incorrectly skipped due to the wrong condition being used to check it.
+* [#1031](https://github.com/shlinkio/shlink/issues/1031) Fixed shortening of twitter URLs with URL validation enabled.
 
 
 ## [2.6.0] - 2021-02-13

+ 4 - 0
module/Core/src/Util/UrlValidator.php

@@ -20,6 +20,8 @@ use const Shlinkio\Shlink\Core\TITLE_TAG_VALUE;
 class UrlValidator implements UrlValidatorInterface, RequestMethodInterface
 {
     private const MAX_REDIRECTS = 15;
+    private const CHROME_USER_AGENT = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) '
+        . 'Chrome/51.0.2704.103 Safari/537.36';
 
     private ClientInterface $httpClient;
     private UrlShortenerOptions $options;
@@ -67,6 +69,8 @@ class UrlValidator implements UrlValidatorInterface, RequestMethodInterface
             return $this->httpClient->request(self::METHOD_GET, $url, [
                 RequestOptions::ALLOW_REDIRECTS => ['max' => self::MAX_REDIRECTS],
                 RequestOptions::IDN_CONVERSION => true,
+                // Making the request with a browser's user agent makes the validation closer to a real user
+                RequestOptions::HEADERS => ['User-Agent' => self::CHROME_USER_AGENT],
             ]);
         } catch (GuzzleException $e) {
             if ($throwOnError) {

+ 11 - 4
module/Core/test/Util/UrlValidatorTest.php

@@ -10,6 +10,7 @@ use GuzzleHttp\Exception\ClientException;
 use GuzzleHttp\RequestOptions;
 use Laminas\Diactoros\Response;
 use Laminas\Diactoros\Stream;
+use PHPUnit\Framework\Assert;
 use PHPUnit\Framework\TestCase;
 use Prophecy\Argument;
 use Prophecy\PhpUnit\ProphecyTrait;
@@ -52,10 +53,16 @@ class UrlValidatorTest extends TestCase
         $request = $this->httpClient->request(
             RequestMethodInterface::METHOD_GET,
             $expectedUrl,
-            [
-                RequestOptions::ALLOW_REDIRECTS => ['max' => 15],
-                RequestOptions::IDN_CONVERSION => true,
-            ],
+            Argument::that(function (array $options) {
+                Assert::assertArrayHasKey(RequestOptions::ALLOW_REDIRECTS, $options);
+                Assert::assertEquals(['max' => 15], $options[RequestOptions::ALLOW_REDIRECTS]);
+                Assert::assertArrayHasKey(RequestOptions::IDN_CONVERSION, $options);
+                Assert::assertTrue($options[RequestOptions::IDN_CONVERSION]);
+                Assert::assertArrayHasKey(RequestOptions::HEADERS, $options);
+                Assert::assertArrayHasKey('User-Agent', $options[RequestOptions::HEADERS]);
+
+                return true;
+            }),
         )->willReturn(new Response());
 
         $this->urlValidator->validateUrl($expectedUrl, null);

+ 18 - 0
module/Rest/test-api/Action/CreateShortUrlTest.php

@@ -297,6 +297,24 @@ class CreateShortUrlTest extends ApiTestCase
         yield 'example domain' => ['example.com'];
     }
 
+    /**
+     * @test
+     * @dataProvider provideTwitterUrls
+     */
+    public function urlsWithBothProtectionCanBeShortenedWithUrlValidationEnabled(string $longUrl): void
+    {
+        [$statusCode] = $this->createShortUrl(['longUrl' => $longUrl, 'validateUrl' => true]);
+        self::assertEquals(self::STATUS_OK, $statusCode);
+    }
+
+    public function provideTwitterUrls(): iterable
+    {
+        yield ['https://twitter.com/shlinkio'];
+        yield ['https://mobile.twitter.com/shlinkio'];
+        yield ['https://twitter.com/shlinkio/status/1360637738421268481'];
+        yield ['https://mobile.twitter.com/shlinkio/status/1360637738421268481'];
+    }
+
     /**
      * @return array {
      *     @var int $statusCode