1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Http\Client\Plugin; |
4
|
|
|
|
5
|
|
|
use Http\Client\Exception\HttpException; |
6
|
|
|
use Http\Client\Plugin\Exception\CircularRedirectionException; |
7
|
|
|
use Http\Client\Plugin\Exception\MultipleRedirectionException; |
8
|
|
|
use Psr\Http\Message\RequestInterface; |
9
|
|
|
use Psr\Http\Message\ResponseInterface; |
10
|
|
|
use Psr\Http\Message\UriInterface; |
11
|
|
|
|
12
|
|
|
/** |
13
|
|
|
* @author Joel Wurtz <[email protected]> |
14
|
|
|
* |
15
|
|
|
* @deprecated since version 1.1, to be removed in 2.0. Use {@link \Http\Client\Common\Plugin\RedirectPlugin} instead. |
16
|
|
|
*/ |
17
|
|
|
class RedirectPlugin extends \Http\Client\Common\Plugin\RedirectPlugin implements Plugin |
|
|
|
|
18
|
|
|
{ |
19
|
|
|
/** |
20
|
|
|
* {@inheritdoc} |
21
|
|
|
*/ |
22
|
11 |
|
public function handleRequest(RequestInterface $request, callable $next, callable $first) |
23
|
|
|
{ |
24
|
|
|
// Check in storage |
25
|
11 |
|
if (array_key_exists($request->getRequestTarget(), $this->redirectStorage)) { |
26
|
1 |
|
$uri = $this->redirectStorage[$request->getRequestTarget()]['uri']; |
27
|
1 |
|
$statusCode = $this->redirectStorage[$request->getRequestTarget()]['status']; |
28
|
1 |
|
$redirectRequest = $this->buildRedirectRequest($request, $uri, $statusCode); |
29
|
|
|
|
30
|
1 |
|
return $first($redirectRequest); |
31
|
|
|
} |
32
|
|
|
|
33
|
10 |
|
return $next($request)->then(function (ResponseInterface $response) use ($request, $first) { |
34
|
10 |
|
$statusCode = $response->getStatusCode(); |
35
|
|
|
|
36
|
10 |
|
if (!array_key_exists($statusCode, $this->redirectCodes)) { |
37
|
|
|
return $response; |
38
|
|
|
} |
39
|
|
|
|
40
|
10 |
|
$uri = $this->createUri($response, $request); |
41
|
6 |
|
$redirectRequest = $this->buildRedirectRequest($request, $uri, $statusCode); |
42
|
6 |
|
$chainIdentifier = spl_object_hash((object) $first); |
43
|
|
|
|
44
|
6 |
|
if (!array_key_exists($chainIdentifier, $this->circularDetection)) { |
45
|
5 |
|
$this->circularDetection[$chainIdentifier] = []; |
46
|
5 |
|
} |
47
|
|
|
|
48
|
6 |
|
$this->circularDetection[$chainIdentifier][] = $request->getRequestTarget(); |
49
|
|
|
|
50
|
6 |
|
if (in_array($redirectRequest->getRequestTarget(), $this->circularDetection[$chainIdentifier])) { |
51
|
1 |
|
throw new CircularRedirectionException('Circular redirection detected', $request, $response); |
|
|
|
|
52
|
|
|
} |
53
|
|
|
|
54
|
5 |
|
if ($this->redirectCodes[$statusCode]['permanent']) { |
55
|
1 |
|
$this->redirectStorage[$request->getRequestTarget()] = [ |
56
|
1 |
|
'uri' => $uri, |
57
|
1 |
|
'status' => $statusCode, |
58
|
|
|
]; |
59
|
1 |
|
} |
60
|
|
|
|
61
|
|
|
// Call redirect request in synchrone |
62
|
5 |
|
$redirectPromise = $first($redirectRequest); |
63
|
|
|
|
64
|
5 |
|
return $redirectPromise->wait(); |
65
|
10 |
|
}); |
66
|
|
|
} |
67
|
|
|
|
68
|
|
|
/** |
69
|
|
|
* Creates a new Uri from the old request and the location header. |
70
|
|
|
* |
71
|
|
|
* @param ResponseInterface $response The redirect response |
72
|
|
|
* @param RequestInterface $request The original request |
73
|
|
|
* |
74
|
|
|
* @throws HttpException If location header is not usable (missing or incorrect) |
75
|
|
|
* @throws MultipleRedirectionException If a 300 status code is received and default location cannot be resolved (doesn't use the location header or not present) |
76
|
|
|
* |
77
|
|
|
* @return UriInterface |
78
|
|
|
*/ |
79
|
10 |
|
private function createUri(ResponseInterface $response, RequestInterface $request) |
|
|
|
|
80
|
|
|
{ |
81
|
10 |
|
if ($this->redirectCodes[$response->getStatusCode()]['multiple'] && (!$this->useDefaultForMultiple || !$response->hasHeader('Location'))) { |
82
|
2 |
|
throw new MultipleRedirectionException('Cannot choose a redirection', $request, $response); |
|
|
|
|
83
|
|
|
} |
84
|
|
|
|
85
|
8 |
|
if (!$response->hasHeader('Location')) { |
86
|
1 |
|
throw new HttpException('Redirect status code, but no location header present in the response', $request, $response); |
87
|
|
|
} |
88
|
|
|
|
89
|
7 |
|
$location = $response->getHeaderLine('Location'); |
90
|
7 |
|
$parsedLocation = parse_url($location); |
91
|
|
|
|
92
|
7 |
|
if (false === $parsedLocation) { |
93
|
1 |
|
throw new HttpException(sprintf('Location %s could not be parsed', $location), $request, $response); |
94
|
|
|
} |
95
|
|
|
|
96
|
6 |
|
$uri = $request->getUri(); |
97
|
|
|
|
98
|
6 |
|
if (array_key_exists('scheme', $parsedLocation)) { |
99
|
1 |
|
$uri = $uri->withScheme($parsedLocation['scheme']); |
100
|
1 |
|
} |
101
|
|
|
|
102
|
6 |
|
if (array_key_exists('host', $parsedLocation)) { |
103
|
1 |
|
$uri = $uri->withHost($parsedLocation['host']); |
104
|
1 |
|
} |
105
|
|
|
|
106
|
6 |
|
if (array_key_exists('port', $parsedLocation)) { |
107
|
1 |
|
$uri = $uri->withPort($parsedLocation['port']); |
108
|
1 |
|
} |
109
|
|
|
|
110
|
6 |
|
if (array_key_exists('path', $parsedLocation)) { |
111
|
6 |
|
$uri = $uri->withPath($parsedLocation['path']); |
112
|
6 |
|
} |
113
|
|
|
|
114
|
6 |
|
if (array_key_exists('query', $parsedLocation)) { |
115
|
1 |
|
$uri = $uri->withQuery($parsedLocation['query']); |
116
|
1 |
|
} else { |
117
|
5 |
|
$uri = $uri->withQuery(''); |
118
|
|
|
} |
119
|
|
|
|
120
|
6 |
|
if (array_key_exists('fragment', $parsedLocation)) { |
121
|
1 |
|
$uri = $uri->withFragment($parsedLocation['fragment']); |
122
|
1 |
|
} else { |
123
|
5 |
|
$uri = $uri->withFragment(''); |
124
|
|
|
} |
125
|
|
|
|
126
|
6 |
|
return $uri; |
127
|
|
|
} |
128
|
|
|
} |
129
|
|
|
|
This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.