1616
1717final class UrlChecker
1818{
19+ /**
20+ * Default maximum number of redirect hops to follow before giving up
21+ * and returning the last redirect response as-is. Guards against
22+ * redirect loops causing unbounded recursion.
23+ */
24+ public const DEFAULT_MAX_REDIRECTS = 5 ;
25+
1926 /**
2027 * @var array<Response>
2128 */
@@ -29,10 +36,10 @@ public static function fake(array $queue): void
2936 self ::$ queue = $ queue ;
3037 }
3138
32- public static function check (string $ url , ?string $ userAgent = null , ?int $ connectTimeout = null , ?int $ timeout = null ): CheckData
39+ public static function check (string $ url , ?string $ userAgent = null , ?int $ connectTimeout = null , ?int $ timeout = null , ? int $ maxRedirects = null ): CheckData
3340 {
3441 try {
35- $ response = (new self ())->getResponse ($ url , $ userAgent , $ connectTimeout , $ timeout );
42+ $ response = (new self ())->getResponse ($ url , $ userAgent , $ connectTimeout , $ timeout, $ maxRedirects ?? self :: DEFAULT_MAX_REDIRECTS );
3643
3744 if (!$ response instanceof ResponseInterface) {
3845 return new CheckData (
@@ -81,7 +88,7 @@ private function getConfig(): array
8188 /**
8289 * @throws GuzzleException
8390 */
84- private function getResponse (string $ url , ?string $ userAgent = null , ?int $ connectTimeout = null , ?int $ timeout = null ): ?ResponseInterface
91+ private function getResponse (string $ url , ?string $ userAgent = null , ?int $ connectTimeout = null , ?int $ timeout = null , int $ redirectsLeft = self :: DEFAULT_MAX_REDIRECTS ): ?ResponseInterface
8592 {
8693 $ response = null ;
8794
@@ -111,8 +118,14 @@ private function getResponse(string $url, ?string $userAgent = null, ?int $conne
111118 }
112119 }
113120
114- if (in_array ($ response ?->getStatusCode(), [301 , 302 , 307 , 308 ], strict: true )) {
115- return $ this ->getResponse ($ response ->getHeader ('Location ' )[0 ] ?? '' );
121+ if ($ redirectsLeft > 0 && in_array ($ response ?->getStatusCode(), [301 , 302 , 307 , 308 ], strict: true )) {
122+ return $ this ->getResponse (
123+ $ response ->getHeader ('Location ' )[0 ] ?? '' ,
124+ $ userAgent ,
125+ $ connectTimeout ,
126+ $ timeout ,
127+ $ redirectsLeft - 1 ,
128+ );
116129 }
117130
118131 return $ response ;
0 commit comments