Permalink
Browse files

[BrowserKit] Adds support for meta refresh

  • Loading branch information...
jhedstrom authored and fabpot committed May 1, 2018
1 parent 4f067e4 commit e419ab2b17167dfd1ad319ea4bbb3097b9458112
Showing with 67 additions and 1 deletion.
  1. +34 −1 Client.php
  2. +33 −0 Tests/ClientTest.php
View
@@ -40,6 +40,7 @@
protected $insulated = false;
protected $redirect;
protected $followRedirects = true;
+ protected $followMetaRefresh = false;
private $maxRedirects = -1;
private $redirectCount = 0;
@@ -68,6 +69,14 @@ public function followRedirects($followRedirect = true)
$this->followRedirects = (bool) $followRedirect;
}
+ /**
+ * Sets whether to automatically follow meta refresh redirects or not.
+ */
+ public function followMetaRefresh(bool $followMetaRefresh = true)
+ {
+ $this->followMetaRefresh = $followMetaRefresh;
+ }
+
/**
* Returns whether client automatically follows redirects or not.
*
@@ -367,7 +376,16 @@ public function request(string $method, string $uri, array $parameters = array()
return $this->crawler = $this->followRedirect();
}
- return $this->crawler = $this->createCrawlerFromContent($this->internalRequest->getUri(), $this->internalResponse->getContent(), $this->internalResponse->getHeader('Content-Type'));
+ $this->crawler = $this->createCrawlerFromContent($this->internalRequest->getUri(), $this->internalResponse->getContent(), $this->internalResponse->getHeader('Content-Type'));
+
+ // Check for meta refresh redirect
+ if ($this->followMetaRefresh && null !== $redirect = $this->getMetaRefreshUrl()) {
+ $this->redirect = $redirect;
+ $this->redirects[serialize($this->history->current())] = true;
+ $this->crawler = $this->followRedirect();
+ }
+
+ return $this->crawler;
}
/**
@@ -563,6 +581,21 @@ public function followRedirect()
return $response;
}
+ /**
+ * @see https://dev.w3.org/html5/spec-preview/the-meta-element.html#attr-meta-http-equiv-refresh
+ */
+ private function getMetaRefreshUrl(): ?string
+ {
+ $metaRefresh = $this->getCrawler()->filter('head meta[http-equiv="refresh"]');
+ foreach ($metaRefresh->extract(array('content')) as $content) {
+ if (preg_match('/^\s*0\s*;\s*URL\s*=\s*(?|\'([^\']++)|"([^"]++)|([^\'"].*))/i', $content, $m)) {
+ return str_replace("\t\r\n", '', rtrim($m[1]));
+ }
+ }
+
+ return null;
+ }
+
/**
* Restarts the client.
*
View
@@ -594,6 +594,39 @@ public function testFollowRedirectDropPostMethod()
}
}
+ /**
+ * @dataProvider getTestsForMetaRefresh
+ */
+ public function testFollowMetaRefresh(string $content, string $expectedEndingUrl, bool $followMetaRefresh = true)
+ {
+ $client = new TestClient();
+ $client->followMetaRefresh($followMetaRefresh);
+ $client->setNextResponse(new Response($content));
+ $client->request('GET', 'http://www.example.com/foo/foobar');
+ $this->assertEquals($expectedEndingUrl, $client->getRequest()->getUri());
+ }
+
+ public function getTestsForMetaRefresh()
+ {
+ return array(
+ array('<html><head><meta http-equiv="Refresh" content="4" /><meta http-equiv="refresh" content="0; URL=http://www.example.com/redirected"/></head></html>', 'http://www.example.com/redirected'),
+ array('<html><head><meta http-equiv="refresh" content="0;URL=http://www.example.com/redirected"/></head></html>', 'http://www.example.com/redirected'),
+ array('<html><head><meta http-equiv="refresh" content="0;URL=\'http://www.example.com/redirected\'"/></head></html>', 'http://www.example.com/redirected'),
+ array('<html><head><meta http-equiv="refresh" content=\'0;URL="http://www.example.com/redirected"\'/></head></html>', 'http://www.example.com/redirected'),
+ array('<html><head><meta http-equiv="refresh" content="0; URL = http://www.example.com/redirected"/></head></html>', 'http://www.example.com/redirected'),
+ array('<html><head><meta http-equiv="refresh" content="0;URL= http://www.example.com/redirected "/></head></html>', 'http://www.example.com/redirected'),
+ array('<html><head><meta http-equiv="refresh" content="0;url=http://www.example.com/redirected "/></head></html>', 'http://www.example.com/redirected'),
+ array('<html><head><noscript><meta http-equiv="refresh" content="0;URL=http://www.example.com/redirected"/></noscript></head></head></html>', 'http://www.example.com/redirected'),
+ // Non-zero timeout should not result in a redirect.
+ array('<html><head><meta http-equiv="refresh" content="4; URL=http://www.example.com/redirected"/></head></html>', 'http://www.example.com/foo/foobar'),
+ array('<html><body></body></html>', 'http://www.example.com/foo/foobar'),
+ // Invalid meta tag placement should not result in a redirect.
+ array('<html><body><meta http-equiv="refresh" content="0;url=http://www.example.com/redirected"/></body></html>', 'http://www.example.com/foo/foobar'),
+ // Valid meta refresh should not be followed if disabled.
+ array('<html><head><meta http-equiv="refresh" content="0;URL=http://www.example.com/redirected"/></head></html>', 'http://www.example.com/foo/foobar', false),
+ );
+ }
+
public function testBack()
{
$client = new TestClient();

0 comments on commit e419ab2

Please sign in to comment.