Verzeichnisstruktur phpBB-3.2.0
- Veröffentlicht
- 06.01.2017
So funktioniert es
|
Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück |
Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
Redirect.php
001 <?php
002 namespace GuzzleHttp\Subscriber;
003
004 use GuzzleHttp\Event\CompleteEvent;
005 use GuzzleHttp\Event\RequestEvents;
006 use GuzzleHttp\Event\SubscriberInterface;
007 use GuzzleHttp\Exception\BadResponseException;
008 use GuzzleHttp\Exception\CouldNotRewindStreamException;
009 use GuzzleHttp\Exception\TooManyRedirectsException;
010 use GuzzleHttp\Message\RequestInterface;
011 use GuzzleHttp\Message\ResponseInterface;
012 use GuzzleHttp\Url;
013
014 /**
015 * Subscriber used to implement HTTP redirects.
016 *
017 * **Request options**
018 *
019 * - redirect: Associative array containing the 'max', 'strict', and 'referer'
020 * keys.
021 *
022 * - max: Maximum number of redirects allowed per-request
023 * - strict: You can use strict redirects by setting this value to ``true``.
024 * Strict redirects adhere to strict RFC compliant redirection (e.g.,
025 * redirect POST with POST) vs doing what most clients do (e.g., redirect
026 * POST request with a GET request).
027 * - referer: Set to true to automatically add the "Referer" header when a
028 * redirect request is sent.
029 * - protocols: Array of allowed protocols. Defaults to 'http' and 'https'.
030 * When a redirect attempts to utilize a protocol that is not white listed,
031 * an exception is thrown.
032 */
033 class Redirect implements SubscriberInterface
034 {
035 public function getEvents()
036 {
037 return ['complete' => ['onComplete', RequestEvents::REDIRECT_RESPONSE]];
038 }
039
040 /**
041 * Rewind the entity body of the request if needed
042 *
043 * @param RequestInterface $redirectRequest
044 * @throws CouldNotRewindStreamException
045 */
046 public static function rewindEntityBody(RequestInterface $redirectRequest)
047 {
048 // Rewind the entity body of the request if needed
049 if ($body = $redirectRequest->getBody()) {
050 // Only rewind the body if some of it has been read already, and
051 // throw an exception if the rewind fails
052 if ($body->tell() && !$body->seek(0)) {
053 throw new CouldNotRewindStreamException(
054 'Unable to rewind the non-seekable request body after redirecting',
055 $redirectRequest
056 );
057 }
058 }
059 }
060
061 /**
062 * Called when a request receives a redirect response
063 *
064 * @param CompleteEvent $event Event emitted
065 * @throws TooManyRedirectsException
066 */
067 public function onComplete(CompleteEvent $event)
068 {
069 $response = $event->getResponse();
070
071 if (substr($response->getStatusCode(), 0, 1) != '3'
072 || !$response->hasHeader('Location')
073 ) {
074 return;
075 }
076
077 $request = $event->getRequest();
078 $config = $request->getConfig();
079
080 // Increment the redirect and initialize the redirect state.
081 if ($redirectCount = $config['redirect_count']) {
082 $config['redirect_count'] = ++$redirectCount;
083 } else {
084 $config['redirect_scheme'] = $request->getScheme();
085 $config['redirect_count'] = $redirectCount = 1;
086 }
087
088 $max = $config->getPath('redirect/max') ?: 5;
089
090 if ($redirectCount > $max) {
091 throw new TooManyRedirectsException(
092 "Will not follow more than {$redirectCount} redirects",
093 $request
094 );
095 }
096
097 $this->modifyRedirectRequest($request, $response);
098 $event->retry();
099 }
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 }
177