Completed
Push — master ( 2baebf...b22d69 )
by smiley
01:43
created

StreamClient   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 113
Duplicated Lines 6.19 %

Coupling/Cohesion

Components 1
Dependencies 8

Importance

Changes 0
Metric Value
dl 7
loc 113
rs 10
c 0
b 0
f 0
wmc 11
lcom 1
cbo 8

3 Methods

Rating   Name   Duplication   Size   Complexity  
A sendRequest() 0 54 3
A getRequestHeaders() 7 17 4
A parseResponseHeaders() 0 21 4

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
/**
3
 * Class StreamClient
4
 *
5
 * @filesource   StreamClient.php
6
 * @created      23.02.2019
7
 * @package      chillerlan\HTTP\Psr18
8
 * @author       smiley <[email protected]>
9
 * @copyright    2019 smiley
10
 * @license      MIT
11
 */
12
13
namespace chillerlan\HTTP\Psr18;
14
15
use Psr\Http\Message\{RequestInterface, ResponseInterface};
16
17
class StreamClient extends HTTPClientAbstract{
18
19
	/**
20
	 * @todo
21
	 *
22
	 * @inheritdoc
23
	 */
24
	public function sendRequest(RequestInterface $request):ResponseInterface{
25
		$uri     = $request->getUri();
26
		$method  = $request->getMethod();
27
		$headers = $this->getRequestHeaders($request);
28
29
		$body    = in_array($method, ['DELETE', 'PATCH', 'POST', 'PUT'], true)
30
			? $request->getBody()->getContents()
31
			: null;
32
33
		$context = stream_context_create([
34
			'http' => [
35
				'method'           => $method,
36
				'header'           => $headers,
37
				'content'          => $body,
38
				'protocol_version' => '1.1',
39
				'user_agent'       => $this->options->user_agent,
40
				'max_redirects'    => 0,
41
				'timeout'          => 5,
42
			],
43
			'ssl' => [
44
				'cafile'              => $this->options->ca_info,
45
				'verify_peer'         => $this->options->ssl_verifypeer,
46
				'verify_depth'        => 3,
47
				'peer_name'           => $uri->getHost(),
48
				'ciphers'             => 'HIGH:!SSLv2:!SSLv3',
49
				'disable_compression' => true,
50
			],
51
		]);
52
53
		$requestUri = (string)$uri->withFragment('');
54
55
		set_error_handler(function ($severity, $msg, $file, $line){
56
			throw new \ErrorException($msg, 0, $severity, $file, $line);
57
		});
58
59
		try{
60
			$responseBody    = file_get_contents($requestUri, false, $context);
61
			$responseHeaders = $this->parseResponseHeaders(get_headers($requestUri, 1, $context));
62
		}catch(\Exception $e){
63
			throw new ClientException($e->getMessage(), $e->getCode());
64
		}
65
66
		restore_error_handler();
67
68
		$response = $this->responseFactory
69
			->createResponse($responseHeaders['statuscode'], $responseHeaders['statustext'])
70
			->withProtocolVersion($responseHeaders['httpversion'])
71
		;
72
73
		$response->getBody()->write($responseBody);
74
		$response->getBody()->rewind();
75
76
		return $response;
77
	}
78
79
	/**
80
	 * @param \Psr\Http\Message\RequestInterface $request
81
	 *
82
	 * @return array
83
	 */
84
	protected function getRequestHeaders(RequestInterface $request):array{
85
		$headers = [];
86
87
		foreach($request->getHeaders() as $name => $values){
88
			$name = strtolower($name);
89
90 View Code Duplication
			foreach($values as $value){
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
91
				$value = (string)$value;
92
93
				// cURL requires a special format for empty headers.
94
				// See https://github.com/guzzle/guzzle/issues/1882 for more details.
95
				$headers[] = $value === '' ? $name.';' : $name.': '.$value;
96
			}
97
		}
98
99
		return $headers;
100
	}
101
102
	/**
103
	 * @param array $headers
104
	 *
105
	 * @return array
106
	 */
107
	protected function parseResponseHeaders(array $headers):array{
108
		$h = [];
109
110
		foreach($headers as $k => $v){
111
112
			if($k === 0 && substr($v, 0, 4) === 'HTTP'){
113
				$status = explode(' ', $v, 3);
114
115
				$h['httpversion'] = explode('/', $status[0], 2)[1];
116
				$h['statuscode']  = intval($status[1]);
117
				$h['statustext']  = trim($status[2]);
118
119
				continue;
120
			}
121
122
			$h[strtolower($k)] = $v;
123
124
		}
125
126
		return $h;
127
	}
128
129
}
130