Completed
Pull Request — master (#23)
by Joel
04:18
created

ResponseReader   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 89
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 92.31%

Importance

Changes 3
Bugs 1 Features 1
Metric Value
wmc 12
c 3
b 1
f 1
lcom 1
cbo 4
dl 0
loc 89
ccs 36
cts 39
cp 0.9231
rs 10

2 Methods

Rating   Name   Duplication   Size   Complexity  
C readResponse() 0 51 10
A createStream() 0 10 2
1
<?php
2
3
namespace Http\Client\Socket;
4
5
use Http\Client\Exception\NetworkException;
6
use Http\Client\Socket\Exception\BrokenPipeException;
7
use Http\Client\Socket\Exception\TimeoutException;
8
use Http\Message\ResponseFactory;
9
use Psr\Http\Message\RequestInterface;
10
use Psr\Http\Message\ResponseInterface;
11
12
/**
13
 * Method for reading response.
14
 *
15
 * Mainly used by SocketHttpClient
16
 *
17
 * @author Joel Wurtz <[email protected]>
18
 */
19
trait ResponseReader
20
{
21
    /**
22
     * @var ResponseFactory For creating response
23
     */
24
    protected $responseFactory;
25
26
    /**
27
     * Read a response from a socket.
28
     *
29
     * @param RequestInterface $request
30
     * @param resource         $socket
31
     *
32
     * @throws TimeoutException    When the socket timed out
33
     * @throws BrokenPipeException When the response cannot be read
34
     *
35
     * @return ResponseInterface
36
     */
37 59
    protected function readResponse(RequestInterface $request, $socket)
38
    {
39 59
        $headers = [];
40 59
        $reason = null;
41
42 59
        while (($line = fgets($socket)) !== false) {
43 58
            if (rtrim($line) === '') {
44 58
                break;
45 1
            }
46 58
            $headers[] = trim($line);
47 58
        }
48
49 59
        $metadatas = stream_get_meta_data($socket);
50
51 59
        if (array_key_exists('timed_out', $metadatas) && true === $metadatas['timed_out']) {
52
            throw new TimeoutException('Error while reading response, stream timed out', $request);
53
        }
54
55 59
        $parts = explode(' ', array_shift($headers), 3);
56
57 59
        if (count($parts) <= 1) {
58 1
            throw new BrokenPipeException('Cannot read the response', $request);
59
        }
60
61 58
        $protocol = substr($parts[0], -3);
62 58
        $status = $parts[1];
63
64 58
        if (isset($parts[2])) {
65 58
            $reason = $parts[2];
66 58
        }
67
68
        // Set the size on the stream if it was returned in the response
69 58
        $responseHeaders = [];
70
71 58
        foreach ($headers as $header) {
72 58
            $headerParts = explode(':', $header, 2);
73
74 58
            if (!array_key_exists(trim($headerParts[0]), $responseHeaders)) {
75 58
                $responseHeaders[trim($headerParts[0])] = [];
76 58
            }
77
78 58
            $responseHeaders[trim($headerParts[0])][] = isset($headerParts[1])
79 58
                ? trim($headerParts[1])
80 58
                : '';
81 58
        }
82
83 58
        $response = $this->responseFactory->createResponse($status, $reason, $responseHeaders, null, $protocol);
84 58
        $stream = $this->createStream($socket, $response);
85
86 58
        return $response->withBody($stream);
87
    }
88
89
    /**
90
     * Create the stream.
91
     *
92
     * @param $socket
93
     * @param ResponseInterface $response
94
     *
95
     * @return Stream
96
     */
97 58
    protected function createStream($socket, ResponseInterface $response)
98
    {
99 58
        $size = null;
100
101 58
        if ($response->hasHeader('Content-Length')) {
102
            $size = (int) $response->getHeaderLine('Content-Length');
103
        }
104
105 58
        return new Stream($socket, $size);
106
    }
107
}
108