diff --git a/lib/Feed.php b/lib/Feed.php index aaa048b..767063c 100644 --- a/lib/Feed.php +++ b/lib/Feed.php @@ -331,8 +331,13 @@ class Feed { protected function computeNextFetch(): \DateTimeImmutable { $now = Date::normalize(time()); if (!$this->modified) { - $diff = $now->getTimestamp() - $this->lastModified->getTimestamp(); - $offset = $this->normalizeDateDiff($diff); + if ($this->lastModified) { + $diff = $now->getTimestamp() - $this->lastModified->getTimestamp(); + $offset = $this->normalizeDateDiff($diff); + } else { + // if no timestamp is available, fall back to three hours + $offset = "3 hours"; + } return $now->modify("+".$offset); } else { // the algorithm for updated feeds (returning 200 rather than 304) uses the same parameters as for 304, diff --git a/tests/cases/Feed/TestFeed.php b/tests/cases/Feed/TestFeed.php index d133ee7..ba2e26b 100644 --- a/tests/cases/Feed/TestFeed.php +++ b/tests/cases/Feed/TestFeed.php @@ -258,50 +258,31 @@ class TestFeed extends \JKingWeb\Arsse\Test\AbstractTest { } } - public function testComputeNextFetchFrom304() { - // if less than half an hour, check in 15 minutes - $t = strtotime("now"); - $f = new Feed(null, $this->base."NextFetch/NotModified?t=$t", Date::transform($t, "http")); - $exp = strtotime("now + 15 minutes"); - $this->assertTime($exp, $f->nextFetch); - $t = strtotime("now - 29 minutes"); - $f = new Feed(null, $this->base."NextFetch/NotModified?t=$t", Date::transform($t, "http")); - $exp = strtotime("now + 15 minutes"); - $this->assertTime($exp, $f->nextFetch); - // if less than an hour, check in 30 minutes - $t = strtotime("now - 30 minutes"); - $f = new Feed(null, $this->base."NextFetch/NotModified?t=$t", Date::transform($t, "http")); - $exp = strtotime("now + 30 minutes"); - $this->assertTime($exp, $f->nextFetch); - $t = strtotime("now - 59 minutes"); - $f = new Feed(null, $this->base."NextFetch/NotModified?t=$t", Date::transform($t, "http")); - $exp = strtotime("now + 30 minutes"); - $this->assertTime($exp, $f->nextFetch); - // if less than three hours, check in an hour - $t = strtotime("now - 1 hour"); - $f = new Feed(null, $this->base."NextFetch/NotModified?t=$t", Date::transform($t, "http")); - $exp = strtotime("now + 1 hour"); - $this->assertTime($exp, $f->nextFetch); - $t = strtotime("now - 2 hours 59 minutes"); - $f = new Feed(null, $this->base."NextFetch/NotModified?t=$t", Date::transform($t, "http")); - $exp = strtotime("now + 1 hour"); - $this->assertTime($exp, $f->nextFetch); - // if more than 36 hours, check in 24 hours - $t = strtotime("now - 36 hours"); + /** @dataProvider provide304Timestamps */ + public function testComputeNextFetchFrom304(string $t, string $exp) { + $t = $t ? strtotime($t) : ""; $f = new Feed(null, $this->base."NextFetch/NotModified?t=$t", Date::transform($t, "http")); - $exp = strtotime("now + 1 day"); + $exp = strtotime($exp); $this->assertTime($exp, $f->nextFetch); - $t = strtotime("now - 2 years"); - $f = new Feed(null, $this->base."NextFetch/NotModified?t=$t", Date::transform($t, "http")); - $exp = strtotime("now + 1 day"); - $this->assertTime($exp, $f->nextFetch); - // otherwise check in three hours - $t = strtotime("now - 3 hours"); - $f = new Feed(null, $this->base."NextFetch/NotModified?t=$t", Date::transform($t, "http")); - $exp = strtotime("now + 3 hours"); - $this->assertTime($exp, $f->nextFetch); - $t = strtotime("now - 35 hours"); - $f = new Feed(null, $this->base."NextFetch/NotModified?t=$t", Date::transform($t, "http")); + } + + public function provide304Timestamps() { + return [ + 'less than half an hour 1' => ["now", "now + 15 minutes"], + 'less than half an hour 2' => ["now - 29 minutes", "now + 15 minutes"], + 'less than one hour 1' => ["now - 30 minutes", "now + 30 minutes"], + 'less than one hour 2' => ["now - 59 minutes", "now + 30 minutes"], + 'less than three hours 1' => ["now - 1 hour", "now + 1 hour"], + 'less than three hours 2' => ["now - 2 hours 59 minutes", "now + 1 hour"], + 'more than thirty-six hours 1' => ["now - 36 hours", "now + 1 day"], + 'more than thirty-six hours 2' => ["now - 2 years", "now + 1 day"], + 'fallback 1' => ["now - 3 hours", "now + 3 hours"], + 'fallback 2' => ["now - 35 hours", "now + 3 hours"], + ]; + } + + public function testComputeNextFetchFrom304WithoutDate() { + $f = new Feed(null, $this->base."NextFetch/NotModifiedEtag"); $exp = strtotime("now + 3 hours"); $this->assertTime($exp, $f->nextFetch); } diff --git a/tests/docroot/Feed/NextFetch/NotModifiedEtag.php b/tests/docroot/Feed/NextFetch/NotModifiedEtag.php new file mode 100644 index 0000000..8b10ad9 --- /dev/null +++ b/tests/docroot/Feed/NextFetch/NotModifiedEtag.php @@ -0,0 +1,6 @@ + 304, + 'cache' => false, + 'fields' => ['ETag: "some-etag"'], +];