Skip to content

Commit 460ea68

Browse files
author
Wazabii
committed
Added client and improved structure
1 parent 972ff4c commit 460ea68

22 files changed

+1068
-651
lines changed

Client.php

Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace PHPFuse\Http;
5+
6+
use PHPFuse\Http\Interfaces\RequestInterface;
7+
use PHPFuse\Http\Interfaces\ResponseInterface;
8+
use PHPFuse\Http\Interfaces\ClientInterface;
9+
10+
use PHPFuse\Http\Exceptions\ClientException;
11+
use PHPFuse\Http\Exceptions\RequestException;
12+
use PHPFuse\Http\Exceptions\NetworkException;
13+
use InvalidArgumentException;
14+
15+
class Client implements ClientInterface {
16+
17+
18+
const DEFAULT_TIMEOUT = 30;
19+
const DEFAULT_AUTH = CURLAUTH_DIGEST;
20+
21+
private $options;
22+
private $ch;
23+
24+
private $requestData;
25+
private $requestDataLength;
26+
private $requestResponse;
27+
private $requestMeta;
28+
29+
function __construct(array $options = []) {
30+
$this->options = $options;
31+
}
32+
33+
/**
34+
* Set option
35+
* https://www.php.net/manual/en/function.curl-setopt.php
36+
* @param int $key
37+
* @param mixed $value
38+
* @return void
39+
*/
40+
public function setOption(int $key, mixed $value): void
41+
{
42+
$this->options[$key] = $value;
43+
}
44+
45+
/**
46+
* Has option
47+
* https://www.php.net/manual/en/function.curl-setopt.php
48+
* @param int $key
49+
* @return void
50+
*/
51+
public function hasOption(int $key): bool
52+
{
53+
return (bool)(isset($this->options[$key]));
54+
}
55+
56+
/**
57+
* Sends a PSR-7 request and returns a PSR-7 response.
58+
* @param RequestInterface $request
59+
* @return ResponseInterface
60+
*/
61+
public function sendRequest(RequestInterface $request): ResponseInterface
62+
{
63+
$this->requestData = (string)$request->getBody();
64+
$this->requestDataLength = strlen($this->requestData);
65+
$this->prepareRequest($request);
66+
67+
try {
68+
69+
if(!extension_loaded('curl')) throw new InvalidArgumentException('You need to enable CURL on your server.');
70+
71+
// Init curl request
72+
$this->ch = curl_init();
73+
$this->buildOptions();
74+
switch($request->getMethod()) {
75+
case 'GET':
76+
$this->get();
77+
break;
78+
case 'POST':
79+
$this->post();
80+
break;
81+
case 'PUT':
82+
$this->put();
83+
break;
84+
case 'PATCH':
85+
$request = $this->patch($request);
86+
break;
87+
case 'DELETE':
88+
$this->delete();
89+
break;
90+
default:
91+
throw new InvalidArgumentException('The requesr method ('.$request->getMethod().') is not supported.');
92+
}
93+
94+
// Execute request
95+
$this->createRequest();
96+
97+
// Close curl request
98+
curl_close($this->ch);
99+
100+
} catch (InvalidArgumentException $e) {
101+
throw new RequestException($e->getMessage(), 1);
102+
103+
} catch (NetworkException $e) {
104+
throw $e;
105+
}
106+
107+
// Retrive the body
108+
return $this->createResponse();
109+
}
110+
111+
/**
112+
* This will open init the request
113+
* @param RequestInterface $request
114+
* @return void
115+
*/
116+
protected function prepareRequest(RequestInterface $request): void
117+
{
118+
$this->setOption(CURLOPT_URL, $request->getUri()->getUri());
119+
$this->setOption(CURLOPT_RETURNTRANSFER, true);
120+
121+
// Default auth option if get user name
122+
if(!$this->hasOption(CURLOPT_HTTPAUTH) && !is_null($request->getUri()->getPart("user"))) {
123+
$this->setOption(CURLOPT_HTTPAUTH, static::DEFAULT_AUTH);
124+
}
125+
126+
if(!$this->hasOption(CURLOPT_TIMEOUT)) {
127+
$this->setOption(CURLOPT_TIMEOUT, static::DEFAULT_TIMEOUT);
128+
}
129+
}
130+
131+
protected function createResponse(): ResponseInterface
132+
{
133+
$stream = new Stream(Stream::TEMP);
134+
$stream->write($this->requestResponse);
135+
if(!$stream->isSeekable()) {
136+
throw new RequestExceptionInterface("Request body is not seekable", 1);
137+
}
138+
$stream->seek(0);
139+
140+
return new Response($stream);
141+
}
142+
143+
/**
144+
* Main request. This will be used for all the request.
145+
* @return void
146+
*/
147+
final protected function createRequest(): void
148+
{
149+
$this->requestResponse = curl_exec($this->ch);
150+
if($this->requestResponse === false) throw new NetworkException(curl_error($this->ch), 1);
151+
$this->requestMeta = curl_getinfo($this->ch);
152+
}
153+
154+
/**
155+
* Get request
156+
* @return void
157+
*/
158+
protected function get(): void
159+
{
160+
// Is empty placeholder at the moment, does not need any more code fo it to work buy..
161+
// you could extend and add your own functionality to it if you want
162+
}
163+
164+
/**
165+
* Post request
166+
* @return void
167+
*/
168+
protected function post(): void
169+
{
170+
curl_setopt($this->ch, CURLOPT_POSTFIELDS, $this->requestData);
171+
curl_setopt($this->ch, CURLOPT_POST, 1);
172+
}
173+
174+
/**
175+
* Put request
176+
* @return void
177+
*/
178+
protected function put(): void
179+
{
180+
$fh = fopen('php://memory', 'rw');
181+
fwrite($fh, $this->requestData);
182+
rewind($fh);
183+
184+
curl_setopt($this->ch, CURLOPT_INFILE, $fh);
185+
curl_setopt($this->ch, CURLOPT_INFILESIZE, $this->requestDataLength);
186+
curl_setopt($this->ch, CURLOPT_PUT, true);
187+
}
188+
189+
/**
190+
* Path request
191+
* @return void
192+
*/
193+
protected function patch(RequestInterface $request): RequestInterface
194+
{
195+
curl_setopt($this->ch, CURLOPT_POSTFIELDS, $this->requestData);
196+
curl_setopt($this->ch, CURLOPT_CUSTOMREQUEST, 'PATCH');
197+
$request = $request->withHeader("content-type", "application/json-patch+json");
198+
return $request;
199+
}
200+
201+
/**
202+
* Delete request
203+
* @return void
204+
*/
205+
protected function delete(): void
206+
{
207+
curl_setopt($this->ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
208+
}
209+
210+
/**
211+
* Will build you options
212+
* @return void
213+
*/
214+
private function buildOptions(): void
215+
{
216+
foreach($this->options as $i => $val) {
217+
if(!is_int($i)) throw new ClientException("The options key needs to be an integer!", 1);
218+
curl_setopt($this->ch, $i, $val);
219+
}
220+
}
221+
222+
/**
223+
* Build the headers
224+
* @return void
225+
*/
226+
private function buildHeaders(RequestInterface $request): void {
227+
$data = array();
228+
foreach($request->getHeaders() as $name => $val) {
229+
$data[] = "{$name}: ".$request->getHeaderLine($name);
230+
}
231+
curl_setopt($this->ch, CURLOPT_HTTPHEADER, $data);
232+
}
233+
}

0 commit comments

Comments
 (0)