From 8df3db566a3a937b45ebf11adb90d265e6f5e2d4 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sun, 17 Nov 2019 20:45:02 +0100 Subject: initial checking of customized version 1.0rc9 --- .../guzzle/src/Guzzle/Http/RedirectPlugin.php | 250 +++++++++++++++++++++ 1 file changed, 250 insertions(+) create mode 100644 vendor/guzzle/guzzle/src/Guzzle/Http/RedirectPlugin.php (limited to 'vendor/guzzle/guzzle/src/Guzzle/Http/RedirectPlugin.php') diff --git a/vendor/guzzle/guzzle/src/Guzzle/Http/RedirectPlugin.php b/vendor/guzzle/guzzle/src/Guzzle/Http/RedirectPlugin.php new file mode 100644 index 0000000..1a824b8 --- /dev/null +++ b/vendor/guzzle/guzzle/src/Guzzle/Http/RedirectPlugin.php @@ -0,0 +1,250 @@ + array('onRequestSent', 100), + 'request.clone' => 'cleanupRequest', + 'request.before_send' => 'cleanupRequest' + ); + } + + /** + * Clean up the parameters of a request when it is cloned + * + * @param Event $event Event emitted + */ + public function cleanupRequest(Event $event) + { + $params = $event['request']->getParams(); + unset($params[self::REDIRECT_COUNT]); + unset($params[self::PARENT_REQUEST]); + } + + /** + * Called when a request receives a redirect response + * + * @param Event $event Event emitted + */ + public function onRequestSent(Event $event) + { + $response = $event['response']; + $request = $event['request']; + + // Only act on redirect requests with Location headers + if (!$response || $request->getParams()->get(self::DISABLE)) { + return; + } + + // Trace the original request based on parameter history + $original = $this->getOriginalRequest($request); + + // Terminating condition to set the effective response on the original request + if (!$response->isRedirect() || !$response->hasHeader('Location')) { + if ($request !== $original) { + // This is a terminating redirect response, so set it on the original request + $response->getParams()->set(self::REDIRECT_COUNT, $original->getParams()->get(self::REDIRECT_COUNT)); + $original->setResponse($response); + $response->setEffectiveUrl($request->getUrl()); + } + return; + } + + $this->sendRedirectRequest($original, $request, $response); + } + + /** + * Get the original request that initiated a series of redirects + * + * @param RequestInterface $request Request to get the original request from + * + * @return RequestInterface + */ + protected function getOriginalRequest(RequestInterface $request) + { + $original = $request; + // The number of redirects is held on the original request, so determine which request that is + while ($parent = $original->getParams()->get(self::PARENT_REQUEST)) { + $original = $parent; + } + + return $original; + } + + /** + * Create a redirect request for a specific request object + * + * Takes into account strict RFC compliant redirection (e.g. redirect POST with POST) vs doing what most clients do + * (e.g. redirect POST with GET). + * + * @param RequestInterface $request Request being redirected + * @param RequestInterface $original Original request + * @param int $statusCode Status code of the redirect + * @param string $location Location header of the redirect + * + * @return RequestInterface Returns a new redirect request + * @throws CouldNotRewindStreamException If the body needs to be rewound but cannot + */ + protected function createRedirectRequest( + RequestInterface $request, + $statusCode, + $location, + RequestInterface $original + ) { + $redirectRequest = null; + $strict = $original->getParams()->get(self::STRICT_REDIRECTS); + + // Switch method to GET for 303 redirects. 301 and 302 redirects also switch to GET unless we are forcing RFC + // compliance to emulate what most browsers do. NOTE: IE only switches methods on 301/302 when coming from a POST. + if ($request instanceof EntityEnclosingRequestInterface && ($statusCode == 303 || (!$strict && $statusCode <= 302))) { + $redirectRequest = RequestFactory::getInstance()->cloneRequestWithMethod($request, 'GET'); + } else { + $redirectRequest = clone $request; + } + + $redirectRequest->setIsRedirect(true); + // Always use the same response body when redirecting + $redirectRequest->setResponseBody($request->getResponseBody()); + + $location = Url::factory($location); + // If the location is not absolute, then combine it with the original URL + if (!$location->isAbsolute()) { + $originalUrl = $redirectRequest->getUrl(true); + // Remove query string parameters and just take what is present on the redirect Location header + $originalUrl->getQuery()->clear(); + $location = $originalUrl->combine((string) $location, true); + } + + $redirectRequest->setUrl($location); + + // Add the parent request to the request before it sends (make sure it's before the onRequestClone event too) + $redirectRequest->getEventDispatcher()->addListener( + 'request.before_send', + $func = function ($e) use (&$func, $request, $redirectRequest) { + $redirectRequest->getEventDispatcher()->removeListener('request.before_send', $func); + $e['request']->getParams()->set(RedirectPlugin::PARENT_REQUEST, $request); + } + ); + + // Rewind the entity body of the request if needed + if ($redirectRequest instanceof EntityEnclosingRequestInterface && $redirectRequest->getBody()) { + $body = $redirectRequest->getBody(); + // Only rewind the body if some of it has been read already, and throw an exception if the rewind fails + if ($body->ftell() && !$body->rewind()) { + throw new CouldNotRewindStreamException( + 'Unable to rewind the non-seekable entity body of the request after redirecting. cURL probably ' + . 'sent part of body before the redirect occurred. Try adding acustom rewind function using on the ' + . 'entity body of the request using setRewindFunction().' + ); + } + } + + return $redirectRequest; + } + + /** + * Prepare the request for redirection and enforce the maximum number of allowed redirects per client + * + * @param RequestInterface $original Original request + * @param RequestInterface $request Request to prepare and validate + * @param Response $response The current response + * + * @return RequestInterface + */ + protected function prepareRedirection(RequestInterface $original, RequestInterface $request, Response $response) + { + $params = $original->getParams(); + // This is a new redirect, so increment the redirect counter + $current = $params[self::REDIRECT_COUNT] + 1; + $params[self::REDIRECT_COUNT] = $current; + // Use a provided maximum value or default to a max redirect count of 5 + $max = isset($params[self::MAX_REDIRECTS]) ? $params[self::MAX_REDIRECTS] : $this->defaultMaxRedirects; + + // Throw an exception if the redirect count is exceeded + if ($current > $max) { + $this->throwTooManyRedirectsException($original, $max); + return false; + } else { + // Create a redirect request based on the redirect rules set on the request + return $this->createRedirectRequest( + $request, + $response->getStatusCode(), + trim($response->getLocation()), + $original + ); + } + } + + /** + * Send a redirect request and handle any errors + * + * @param RequestInterface $original The originating request + * @param RequestInterface $request The current request being redirected + * @param Response $response The response of the current request + * + * @throws BadResponseException|\Exception + */ + protected function sendRedirectRequest(RequestInterface $original, RequestInterface $request, Response $response) + { + // Validate and create a redirect request based on the original request and current response + if ($redirectRequest = $this->prepareRedirection($original, $request, $response)) { + try { + $redirectRequest->send(); + } catch (BadResponseException $e) { + $e->getResponse(); + if (!$e->getResponse()) { + throw $e; + } + } + } + } + + /** + * Throw a too many redirects exception for a request + * + * @param RequestInterface $original Request + * @param int $max Max allowed redirects + * + * @throws TooManyRedirectsException when too many redirects have been issued + */ + protected function throwTooManyRedirectsException(RequestInterface $original, $max) + { + $original->getEventDispatcher()->addListener( + 'request.complete', + $func = function ($e) use (&$func, $original, $max) { + $original->getEventDispatcher()->removeListener('request.complete', $func); + $str = "{$max} redirects were issued for this request:\n" . $e['request']->getRawHeaders(); + throw new TooManyRedirectsException($str); + } + ); + } +} -- cgit v1.2.3-54-g00ecf