Skip to content

Commit 08bd3f9

Browse files
committed
🚿
1 parent 0fa021a commit 08bd3f9

6 files changed

+156
-166
lines changed

src/CurlClient.php

Lines changed: 28 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -55,63 +55,48 @@ public function __construct(ContainerInterface $options){
5555
}
5656

5757
/** @inheritdoc */
58-
public function request(string $url, array $params = null, string $method = null, $body = null, array $headers = null):HTTPResponseInterface{
58+
protected function getResponse():HTTPResponseInterface{
5959
$this->responseHeaders = new \stdClass;
6060

61-
try{
62-
$parsedURL = parse_url($url);
61+
$headers = $this->normalizeRequestHeaders($this->requestHeaders);
62+
$options = [CURLOPT_CUSTOMREQUEST => $this->requestMethod];
6363

64-
if(!isset($parsedURL['host']) || $parsedURL['scheme'] !== 'https'){
65-
trigger_error('invalid URL');
66-
}
67-
68-
$method = strtoupper($method ?? 'POST');
69-
$headers = $this->normalizeRequestHeaders($headers ?? []);
70-
$options = [CURLOPT_CUSTOMREQUEST => $method];
71-
72-
if(in_array($method, ['PATCH', 'POST', 'PUT', 'DELETE'], true)){
64+
if(in_array($this->requestMethod, ['PATCH', 'POST', 'PUT', 'DELETE'], true)){
7365

74-
if($method === 'POST'){
75-
$options = [CURLOPT_POST => true];
76-
77-
if(!isset($headers['Content-type']) && is_array($body)){
78-
$headers += ['Content-type: application/x-www-form-urlencoded'];
79-
$body = http_build_query($body, '', '&', PHP_QUERY_RFC1738);
80-
}
66+
if($this->requestMethod === 'POST'){
67+
$options = [CURLOPT_POST => true];
8168

69+
if(!isset($headers['Content-type']) && is_array($this->requestBody)){
70+
$headers += ['Content-type: application/x-www-form-urlencoded'];
71+
$this->requestBody = http_build_query($this->requestBody, '', '&', PHP_QUERY_RFC1738);
8272
}
83-
84-
$options += [CURLOPT_POSTFIELDS => $body];
8573
}
8674

87-
$headers += [
88-
'Host: '.$parsedURL['host'],
89-
'Connection: close',
90-
];
75+
$options += [CURLOPT_POSTFIELDS => $this->requestBody];
76+
}
9177

92-
$params = $params ?? [];
93-
$url = $url.(!empty($params) ? '?'.http_build_query($params) : '');
78+
$headers += [
79+
'Host: '.$this->parsedURL['host'],
80+
'Connection: close',
81+
];
9482

95-
$options += [
96-
CURLOPT_URL => $url,
97-
CURLOPT_HTTPHEADER => $headers,
98-
CURLOPT_HEADERFUNCTION => [$this, 'headerLine'],
99-
];
83+
$url = $this->requestURL.(!empty($this->requestParams) ? '?'.$this->buildQuery($this->requestParams) : '');
10084

101-
curl_setopt_array($this->http, $options);
85+
$options += [
86+
CURLOPT_URL => $url,
87+
CURLOPT_HTTPHEADER => $headers,
88+
CURLOPT_HEADERFUNCTION => [$this, 'headerLine'],
89+
];
10290

103-
$response = curl_exec($this->http);
91+
curl_setopt_array($this->http, $options);
10492

105-
return new HTTPResponse([
106-
'headers' => $this->responseHeaders,
107-
'body' => $response,
108-
]);
109-
110-
}
111-
catch(\Exception $e){
112-
throw new HTTPClientException($e->getMessage());
113-
}
93+
$response = curl_exec($this->http);
11494

95+
return new HTTPResponse([
96+
'url' => $url,
97+
'headers' => $this->responseHeaders,
98+
'body' => $response,
99+
]);
115100
}
116101

117102
/**

src/GuzzleClient.php

Lines changed: 26 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -43,51 +43,39 @@ public function setClient(Client $http):HTTPClientInterface{
4343
}
4444

4545
/** @inheritdoc */
46-
public function request(string $url, array $params = null, string $method = null, $body = null, array $headers = null):HTTPResponseInterface{
47-
48-
try{
49-
$parsedURL = parse_url($url);
50-
$method = strtoupper($method ?? 'POST');
51-
52-
if(!isset($parsedURL['host']) || $parsedURL['scheme'] !== 'https'){
53-
trigger_error('invalid URL');
46+
protected function getResponse():HTTPResponseInterface{
47+
// @link http://docs.guzzlephp.org/en/stable/request-options.html
48+
$options = [
49+
'query' => $this->requestParams,
50+
'headers' => $this->requestHeaders,
51+
'http_errors' => false, // no exceptions on HTTP errors plz
52+
];
53+
54+
if(in_array($this->requestMethod, ['PATCH', 'POST', 'PUT', 'DELETE'], true)){
55+
56+
if(is_scalar($this->requestBody) || $this->requestBody instanceof StreamInterface){
57+
$options['body'] = $this->requestBody; // @codeCoverageIgnore
5458
}
55-
56-
// @link http://docs.guzzlephp.org/en/stable/request-options.html
57-
$options = [
58-
'query' => $params ?? [],
59-
'headers' => $headers ?? [],
60-
'http_errors' => false, // no exceptions on HTTP errors plz
61-
];
62-
63-
if(in_array($method, ['PATCH', 'POST', 'PUT', 'DELETE'], true)){
64-
65-
if(is_scalar($body) || $body instanceof StreamInterface){
66-
$options['body'] = $body; // @codeCoverageIgnore
67-
}
68-
elseif(in_array($method, ['PATCH', 'POST', 'PUT'], true) && is_array($body)){
69-
$options['form_params'] = $body;
70-
}
71-
59+
elseif(in_array($this->requestMethod, ['PATCH', 'POST', 'PUT'], true) && is_array($this->requestBody)){
60+
$options['form_params'] = $this->requestBody;
7261
}
7362

74-
$response = $this->http->request($method, explode('?', $url)[0], $options);
63+
}
7564

76-
$responseHeaders = $this->parseResponseHeaders($response->getHeaders());
77-
$responseHeaders->statuscode = $response->getStatusCode();
78-
$responseHeaders->statustext = $response->getReasonPhrase();
79-
$responseHeaders->httpversion = $response->getProtocolVersion();
65+
$url = explode('?', $this->requestURL)[0];
8066

81-
return new HTTPResponse([
82-
'headers' => $responseHeaders,
83-
'body' => $response->getBody(),
84-
]);
67+
$response = $this->http->request($this->requestMethod, $url, $options); // @todo: merge query params
8568

86-
}
87-
catch(\Exception $e){
88-
throw new HTTPClientException('fetch error: '.$e->getMessage());
89-
}
69+
$responseHeaders = $this->parseResponseHeaders($response->getHeaders());
70+
$responseHeaders->statuscode = $response->getStatusCode();
71+
$responseHeaders->statustext = $response->getReasonPhrase();
72+
$responseHeaders->httpversion = $response->getProtocolVersion();
9073

74+
return new HTTPResponse([
75+
'url' => $url,
76+
'headers' => $responseHeaders,
77+
'body' => $response->getBody(),
78+
]);
9179
}
9280

9381
/**

src/HTTPClientAbstract.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,55 @@ abstract class HTTPClientAbstract implements HTTPClientInterface, LoggerAwareInt
3030
*/
3131
protected $options;
3232

33+
protected $requestURL;
34+
protected $parsedURL;
35+
protected $requestParams;
36+
protected $requestMethod;
37+
protected $requestBody;
38+
protected $requestHeaders;
39+
3340
/** @inheritdoc */
3441
public function __construct(ContainerInterface $options, LoggerInterface $logger = null){
3542
$this->options = $options;
3643
$this->logger = $logger ?? new NullLogger;
3744
}
3845

46+
/**
47+
* @return \chillerlan\HTTP\HTTPResponseInterface
48+
*/
49+
abstract protected function getResponse():HTTPResponseInterface;
50+
51+
/**
52+
* @param string $url
53+
* @param array|null $params
54+
* @param string|null $method
55+
* @param null $body
56+
* @param array|null $headers
57+
*
58+
* @return \chillerlan\HTTP\HTTPResponseInterface
59+
* @throws \chillerlan\HTTP\HTTPClientException
60+
*/
61+
public function request(string $url, array $params = null, string $method = null, $body = null, array $headers = null):HTTPResponseInterface{
62+
$this->requestURL = $url;
63+
$this->parsedURL = parse_url($this->requestURL);
64+
$this->requestParams = $params ?? [];
65+
$this->requestMethod = strtoupper($method ?? 'POST');
66+
$this->requestBody = $body;
67+
$this->requestHeaders = $headers ?? [];
68+
69+
if(!isset($this->parsedURL['host']) || !in_array($this->parsedURL['scheme'], $this::ALLOWED_SCHEMES, true)){
70+
throw new HTTPClientException('invalid URL');
71+
}
72+
73+
try{
74+
return $this->getResponse();
75+
}
76+
catch(\Exception $e){
77+
throw new HTTPClientException('fetch error: '.$e->getMessage());
78+
}
79+
80+
}
81+
3982
/** @inheritdoc */
4083
public function normalizeRequestHeaders(array $headers):array {
4184
$normalized_headers = [];

src/HTTPClientInterface.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
interface HTTPClientInterface{
1616

17+
const ALLOWED_SCHEMES = ['http', 'https'];
18+
1719
/**
1820
* @param string $url
1921
* @param array|null $params

src/StreamClient.php

Lines changed: 40 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -32,63 +32,49 @@ public function __construct(ContainerInterface $options){
3232
}
3333

3434
/** @inheritdoc */
35-
public function request(string $url, array $params = null, string $method = null, $body = null, array $headers = null):HTTPResponseInterface{
35+
protected function getResponse():HTTPResponseInterface{
36+
$headers = $this->normalizeRequestHeaders($this->requestHeaders);
3637

37-
try{
38-
$parsedURL = parse_url($url);
39-
40-
if(!isset($parsedURL['host']) || $parsedURL['scheme'] !== 'https'){
41-
trigger_error('invalid URL');
42-
}
43-
44-
$method = strtoupper($method ?? 'POST');
45-
$headers = $this->normalizeRequestHeaders($headers ?? []);
46-
47-
if(in_array($method, ['PATCH', 'POST', 'PUT', 'DELETE']) && is_array($body)){
48-
$body = http_build_query($body, '', '&', PHP_QUERY_RFC1738);
49-
50-
$headers['Content-Type'] = 'Content-Type: application/x-www-form-urlencoded';
51-
$headers['Content-length'] = 'Content-length: '.strlen($body);
52-
}
53-
54-
$headers['Host'] = 'Host: '.$parsedURL['host'].(!empty($parsedURL['port']) ? ':'.$parsedURL['port'] : '');
55-
$headers['Connection'] = 'Connection: close';
56-
57-
$params = $params ?? [];
58-
$url = $url.(!empty($params) ? '?'.http_build_query($params) : '');
59-
60-
$context = stream_context_create([
61-
'http' => [
62-
'method' => $method,
63-
'header' => $headers,
64-
'content' => $body,
65-
'protocol_version' => '1.1',
66-
'user_agent' => $this->options->user_agent,
67-
'max_redirects' => 0,
68-
'timeout' => 5,
69-
],
70-
'ssl' => [
71-
'cafile' => $this->options->ca_info,
72-
'verify_peer' => true,
73-
'verify_depth' => 3,
74-
'peer_name' => $parsedURL['host'],
75-
'ciphers' => 'HIGH:!SSLv2:!SSLv3',
76-
'disable_compression' => true,
77-
],
78-
]);
79-
80-
$response = file_get_contents($url, false, $context);
81-
$responseHeaders = get_headers($url, 1);
82-
83-
return new HTTPResponse([
84-
'headers' => $this->parseResponseHeaders($responseHeaders),
85-
'body' => trim($response),
86-
]);
38+
if(in_array($this->requestMethod, ['PATCH', 'POST', 'PUT', 'DELETE']) && is_array($this->requestBody)){
39+
$this->requestBody = http_build_query($this->requestBody, '', '&', PHP_QUERY_RFC1738);
8740

41+
$headers['Content-Type'] = 'Content-Type: application/x-www-form-urlencoded';
42+
$headers['Content-length'] = 'Content-length: '.strlen($this->requestBody);
8843
}
89-
catch(\Exception $e){
90-
throw new HTTPClientException($e->getMessage());
91-
}
44+
45+
$headers['Host'] = 'Host: '.$this->parsedURL['host'].(!empty($this->parsedURL['port']) ? ':'.$this->parsedURL['port'] : '');
46+
$headers['Connection'] = 'Connection: close';
47+
48+
$url = $this->requestURL.(!empty($this->requestParams) ? '?'.$this->buildQuery($this->requestParams) : '');
49+
50+
$context = stream_context_create([
51+
'http' => [
52+
'method' => $this->requestMethod,
53+
'header' => $headers,
54+
'content' => $this->requestBody,
55+
'protocol_version' => '1.1',
56+
'user_agent' => $this->options->user_agent,
57+
'max_redirects' => 0,
58+
'timeout' => 5,
59+
],
60+
'ssl' => [
61+
'cafile' => $this->options->ca_info,
62+
'verify_peer' => true,
63+
'verify_depth' => 3,
64+
'peer_name' => $this->parsedURL['host'],
65+
'ciphers' => 'HIGH:!SSLv2:!SSLv3',
66+
'disable_compression' => true,
67+
],
68+
]);
69+
70+
$response = file_get_contents($url, false, $context);
71+
$responseHeaders = get_headers($url, 1);
72+
73+
return new HTTPResponse([
74+
'url' => $url,
75+
'headers' => $this->parseResponseHeaders($responseHeaders),
76+
'body' => trim($response),
77+
]);
9278

9379
}
9480

src/TinyCurlClient.php

Lines changed: 17 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -42,37 +42,23 @@ public function setClient(Request $http):HTTPClientInterface{
4242
}
4343

4444
/** @inheritdoc */
45-
public function request(string $url, array $params = null, string $method = null, $body = null, array $headers = null):HTTPResponseInterface{
46-
47-
try{
48-
49-
$parsedURL = parse_url($url);
50-
51-
if(!isset($parsedURL['host']) || !in_array($parsedURL['scheme'], ['http', 'https'], true)){
52-
trigger_error('invalid URL');
53-
}
54-
55-
$url = new URL(
56-
explode('?', $url)[0],
57-
$params ?? [],
58-
$method ?? 'POST',
59-
$body,
60-
$headers ?? []
61-
);
62-
63-
$response = $this->http->fetch($url);
64-
65-
return new HTTPResponse([
66-
'url' => $url->__toString(),
67-
'headers' => $response->headers,
68-
'body' => $response->body->content,
69-
]);
70-
71-
}
72-
catch(\Exception $e){
73-
throw new HTTPClientException('fetch error: '.$e->getMessage());
74-
}
75-
45+
protected function getResponse():HTTPResponseInterface{
46+
47+
$url = new URL(
48+
explode('?', $this->requestURL)[0],
49+
$this->requestParams,
50+
$this->requestMethod,
51+
$this->requestBody,
52+
$this->requestHeaders
53+
);
54+
55+
$response = $this->http->fetch($url);
56+
57+
return new HTTPResponse([
58+
'url' => $url->__toString(),
59+
'headers' => $response->headers,
60+
'body' => $response->body->content,
61+
]);
7662
}
7763

7864
}

0 commit comments

Comments
 (0)