[ Index ] |
PHP Cross Reference of phpBB-3.2.11-deutsch |
[Summary view] [Print] [Text view]
1 <?php 2 namespace GuzzleHttp\Subscriber; 3 4 use GuzzleHttp\Event\CompleteEvent; 5 use GuzzleHttp\Event\RequestEvents; 6 use GuzzleHttp\Event\SubscriberInterface; 7 use GuzzleHttp\Exception\BadResponseException; 8 use GuzzleHttp\Exception\CouldNotRewindStreamException; 9 use GuzzleHttp\Exception\TooManyRedirectsException; 10 use GuzzleHttp\Message\RequestInterface; 11 use GuzzleHttp\Message\ResponseInterface; 12 use GuzzleHttp\Url; 13 14 /** 15 * Subscriber used to implement HTTP redirects. 16 * 17 * **Request options** 18 * 19 * - redirect: Associative array containing the 'max', 'strict', and 'referer' 20 * keys. 21 * 22 * - max: Maximum number of redirects allowed per-request 23 * - strict: You can use strict redirects by setting this value to ``true``. 24 * Strict redirects adhere to strict RFC compliant redirection (e.g., 25 * redirect POST with POST) vs doing what most clients do (e.g., redirect 26 * POST request with a GET request). 27 * - referer: Set to true to automatically add the "Referer" header when a 28 * redirect request is sent. 29 * - protocols: Array of allowed protocols. Defaults to 'http' and 'https'. 30 * When a redirect attempts to utilize a protocol that is not white listed, 31 * an exception is thrown. 32 */ 33 class Redirect implements SubscriberInterface 34 { 35 public function getEvents() 36 { 37 return ['complete' => ['onComplete', RequestEvents::REDIRECT_RESPONSE]]; 38 } 39 40 /** 41 * Rewind the entity body of the request if needed 42 * 43 * @param RequestInterface $redirectRequest 44 * @throws CouldNotRewindStreamException 45 */ 46 public static function rewindEntityBody(RequestInterface $redirectRequest) 47 { 48 // Rewind the entity body of the request if needed 49 if ($body = $redirectRequest->getBody()) { 50 // Only rewind the body if some of it has been read already, and 51 // throw an exception if the rewind fails 52 if ($body->tell() && !$body->seek(0)) { 53 throw new CouldNotRewindStreamException( 54 'Unable to rewind the non-seekable request body after redirecting', 55 $redirectRequest 56 ); 57 } 58 } 59 } 60 61 /** 62 * Called when a request receives a redirect response 63 * 64 * @param CompleteEvent $event Event emitted 65 * @throws TooManyRedirectsException 66 */ 67 public function onComplete(CompleteEvent $event) 68 { 69 $response = $event->getResponse(); 70 71 if (substr($response->getStatusCode(), 0, 1) != '3' 72 || !$response->hasHeader('Location') 73 ) { 74 return; 75 } 76 77 $request = $event->getRequest(); 78 $config = $request->getConfig(); 79 80 // Increment the redirect and initialize the redirect state. 81 if ($redirectCount = $config['redirect_count']) { 82 $config['redirect_count'] = ++$redirectCount; 83 } else { 84 $config['redirect_scheme'] = $request->getScheme(); 85 $config['redirect_count'] = $redirectCount = 1; 86 } 87 88 $max = $config->getPath('redirect/max') ?: 5; 89 90 if ($redirectCount > $max) { 91 throw new TooManyRedirectsException( 92 "Will not follow more than {$redirectCount} redirects", 93 $request 94 ); 95 } 96 97 $this->modifyRedirectRequest($request, $response); 98 $event->retry(); 99 } 100 101 private function modifyRedirectRequest( 102 RequestInterface $request, 103 ResponseInterface $response 104 ) { 105 $config = $request->getConfig(); 106 $protocols = $config->getPath('redirect/protocols') ?: ['http', 'https']; 107 108 // Use a GET request if this is an entity enclosing request and we are 109 // not forcing RFC compliance, but rather emulating what all browsers 110 // would do. 111 $statusCode = $response->getStatusCode(); 112 if ($statusCode == 303 || 113 ($statusCode <= 302 && $request->getBody() && !$config->getPath('redirect/strict')) 114 ) { 115 $request->setMethod('GET'); 116 $request->setBody(null); 117 } 118 119 $previousUrl = $request->getUrl(); 120 $this->setRedirectUrl($request, $response, $protocols); 121 $this->rewindEntityBody($request); 122 123 // Add the Referer header if it is told to do so and only 124 // add the header if we are not redirecting from https to http. 125 if ($config->getPath('redirect/referer') 126 && ($request->getScheme() == 'https' || $request->getScheme() == $config['redirect_scheme']) 127 ) { 128 $url = Url::fromString($previousUrl); 129 $url->setUsername(null); 130 $url->setPassword(null); 131 $request->setHeader('Referer', (string) $url); 132 } else { 133 $request->removeHeader('Referer'); 134 } 135 } 136 137 /** 138 * Set the appropriate URL on the request based on the location header 139 * 140 * @param RequestInterface $request 141 * @param ResponseInterface $response 142 * @param array $protocols 143 */ 144 private function setRedirectUrl( 145 RequestInterface $request, 146 ResponseInterface $response, 147 array $protocols 148 ) { 149 $location = $response->getHeader('Location'); 150 $location = Url::fromString($location); 151 152 // Combine location with the original URL if it is not absolute. 153 if (!$location->isAbsolute()) { 154 $originalUrl = Url::fromString($request->getUrl()); 155 // Remove query string parameters and just take what is present on 156 // the redirect Location header 157 $originalUrl->getQuery()->clear(); 158 $location = $originalUrl->combine($location); 159 } 160 161 // Ensure that the redirect URL is allowed based on the protocols. 162 if (!in_array($location->getScheme(), $protocols)) { 163 throw new BadResponseException( 164 sprintf( 165 'Redirect URL, %s, does not use one of the allowed redirect protocols: %s', 166 $location, 167 implode(', ', $protocols) 168 ), 169 $request, 170 $response 171 ); 172 } 173 174 $request->setUrl($location); 175 } 176 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Nov 11 20:33:01 2020 | Cross-referenced by PHPXref 0.7.1 |