]> git.mxchange.org Git - friendica.git/commitdiff
Update feed URL after permanent redirect
authorMatthew Exon <git.mexon@spamgourmet.com>
Mon, 1 Jul 2024 16:50:13 +0000 (18:50 +0200)
committerMatthew Exon <git.mexon@spamgourmet.com>
Mon, 1 Jul 2024 16:50:13 +0000 (18:50 +0200)
src/Model/Contact.php
src/Network/HTTPClient/Capability/ICanHandleHttpResponses.php
src/Network/HTTPClient/Response/CurlResult.php
src/Network/HTTPClient/Response/GuzzleResponse.php
src/Worker/OnePoll.php

index 5cd77048c9624dec92963cca43b595bd43e6c1c5..0dc662659e4ea58a6317c4ba811a862f9d275522 100644 (file)
@@ -2445,6 +2445,19 @@ class Contact
                }
        }
 
+       /**
+        * Updates the poll URL of a contact.  This is the right function to call if there is a redirect.
+        *
+        * @param integer $id  contact id
+        * @param string  $url The new URL to use for polling
+        *
+        * @throws \Exception
+        */
+       public static function updatePollUrl(int $id, string $url)
+       {
+               self::update(['poll', $url], ['id' => $id]);
+       }
+
        /**
         * Helper function for "updateFromProbe". Updates personal and public contact
         *
index 68c8eda2d854076e97318478b406b5b039be30ba..5eb2e9bf4db926e617500d397675fc8e329b1922 100644 (file)
@@ -90,10 +90,20 @@ interface ICanHandleHttpResponses
        public function getUrl(): string;
 
        /**
+        * If the request was redirected to another URL, gets the final URL requested
         * @return string
         */
        public function getRedirectUrl(): string;
 
+       /**
+        * If the request was redirected to another URL, indicates if the redirect is permanent.
+        * If the request was not redirected, returns false.
+        * If the request was redirected multiple times, returns true only if all of the redirects were permanent.
+        *
+        * @return bool True if the redirect is permanent
+        */
+       public function redirectIsPermanent(): bool;
+
        /**
         * Getter for body
         *
index 75d390eac7ad73491f75a31481b5e92f51d9b356..79aa9c722f6d382a49c396e1284b109eebcbd069 100644 (file)
@@ -81,6 +81,11 @@ class CurlResult implements ICanHandleHttpResponses
         */
        private $isRedirectUrl;
 
+       /**
+        * @var boolean true if the URL has a permanent redirect
+        */
+       private $redirectIsPermanent;
+
        /**
         * @var boolean true if the curl request timed out
         */
@@ -197,7 +202,7 @@ class CurlResult implements ICanHandleHttpResponses
                        $this->redirectUrl = $this->info['url'];
                }
 
-               if ($this->returnCode == 301 || $this->returnCode == 302 || $this->returnCode == 303 || $this->returnCode == 307) {
+               if ($this->returnCode == 301 || $this->returnCode == 302 || $this->returnCode == 303 || $this->returnCode == 307 || $this->returnCode == 308) {
                        $redirect_parts = parse_url($this->info['redirect_url'] ?? '');
                        if (empty($redirect_parts)) {
                                $redirect_parts = [];
@@ -224,10 +229,11 @@ class CurlResult implements ICanHandleHttpResponses
                        }
 
                        $this->redirectUrl = (string)Uri::fromParts((array)$redirect_parts);
-
                        $this->isRedirectUrl = true;
+                       $this->redirectIsPermanent = $this->returnCode == 301 or $this->returnCode == 308;
                } else {
                        $this->isRedirectUrl = false;
+                       $this->redirectIsPermanent = false;
                }
        }
 
@@ -340,6 +346,12 @@ class CurlResult implements ICanHandleHttpResponses
                return $this->isRedirectUrl;
        }
 
+       /** {@inheritDoc} */
+       public function redirectIsPermanent(): bool
+       {
+               return $this->redirectIsPermanent;
+       }
+
        /** {@inheritDoc} */
        public function getErrorNumber(): int
        {
index d277f2a8df05bffeb7f44f30049a6c5e53c4dcbe..6678a6b8a8c25582e67b45d960b624f27fb570a0 100644 (file)
@@ -52,6 +52,8 @@ class GuzzleResponse extends Response implements ICanHandleHttpResponses, Respon
        private $redirectUrl = '';
        /** @var bool */
        private $isRedirectUrl = false;
+       /** @var bool */
+       private $redirectIsPermanent = false;
 
        public function __construct(ResponseInterface $response, string $url, $errorNumber = 0, $error = '')
        {
@@ -91,6 +93,13 @@ class GuzzleResponse extends Response implements ICanHandleHttpResponses, Respon
                if (count($headersRedirect) > 0) {
                        $this->redirectUrl   = $headersRedirect[0];
                        $this->isRedirectUrl = true;
+
+                       $this->redirectIsPermanent = true;
+                       foreach (($response->getHeader(RedirectMiddleware::STATUS_HISTORY_HEADER) ?? []) as $history) {
+                               if (preg_match('/30(2|3|4|7)/', $history)) {
+                                       $this->redirectIsPermanent = false;
+                               }
+                       }
                }
        }
 
@@ -145,6 +154,12 @@ class GuzzleResponse extends Response implements ICanHandleHttpResponses, Respon
                return $this->isRedirectUrl;
        }
 
+       /** {@inheritDoc} */
+       public function redirectIsPermanent(): bool
+       {
+               return $this->redirectIsPermanent;
+       }
+
        /** {@inheritDoc} */
        public function getErrorNumber(): int
        {
index 838f30a4e431667b9d105184474ecd79e681b8ae..7c784ab7049a47775b1d70a615b64492934f4dc6 100644 (file)
@@ -167,12 +167,23 @@ class OnePoll
                $cookiejar = tempnam(System::getTempPath(), 'cookiejar-onepoll-');
                $curlResult = DI::httpClient()->get($contact['poll'], HttpClientAccept::FEED_XML, [HttpClientOptions::COOKIEJAR => $cookiejar, HttpClientOptions::REQUEST => HttpClientRequest::FEEDFETCHER]);
                unlink($cookiejar);
+               Logger::debug('Polled feed', ['url' => $contact['poll'], 'http-code' => $curlResult->getReturnCode(), 'redirect-url' => $curlResult->getRedirectUrl()]);
 
                if ($curlResult->isTimeout()) {
                        Logger::notice('Polling timed out', ['id' => $contact['id'], 'url' => $contact['poll']]);
                        return false;
                }
 
+               if ($curlResult->redirectIsPermanent()) {
+                       Logger::notice('Poll address permanently changed', [
+                               'id' => $contact['id'],
+                               'uid' => $contact['uid'],
+                               'old' => $contact['poll'],
+                               'new' => $curlResult->getRedirectUrl(),
+                       ]);
+                       $success = Contact::updatePollUrl($contact['id'], $curlResult->getRedirectUrl());
+               }
+
                $xml = $curlResult->getBodyString();
                if (empty($xml)) {
                        Logger::notice('Empty content', ['id' => $contact['id'], 'url' => $contact['poll']]);