Completed
Pull Request — master (#64)
by Márk
05:20
created

RedirectPlugin::__construct()   A

Complexity

Conditions 3
Paths 1

Size

Total Lines 21
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 3.0021

Importance

Changes 3
Bugs 1 Features 0
Metric Value
c 3
b 1
f 0
dl 0
loc 21
ccs 15
cts 16
cp 0.9375
rs 9.3142
cc 3
eloc 14
nc 1
nop 1
crap 3.0021
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
0 ignored issues
show
Deprecated Code introduced by
The interface Http\Client\Plugin\Plugin has been deprecated with message: since version 1.1, to be removed in 2.0. Use {@link \Http\Client\Common\Plugin} instead.

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.

Loading history...
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);
0 ignored issues
show
Deprecated Code introduced by
The class Http\Client\Plugin\Excep...larRedirectionException has been deprecated with message: since version 1.1, to be removed in 2.0. Use {@link \Http\Client\Common\Exception\CircularRedirectionException} instead.

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.

Loading history...
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)
0 ignored issues
show
Bug introduced by
Consider using a different method name as you override a private method of the parent class.

Overwriting private methods is generally fine as long as you also use private visibility. It might still be preferable for understandability to use a different method name.

Loading history...
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);
0 ignored issues
show
Deprecated Code introduced by
The class Http\Client\Plugin\Excep...pleRedirectionException has been deprecated with message: since version 1.1, to be removed in 2.0. Use {@link \Http\Client\Common\Exception\MultipleRedirectionException} instead.

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.

Loading history...
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