Skip to content

Commit 333ffc2

Browse files
committed
Add missing http methods
1 parent 19b60e1 commit 333ffc2

File tree

2 files changed

+142
-25
lines changed

2 files changed

+142
-25
lines changed

src/Http/Client/HttpClient.php

Lines changed: 84 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,7 @@ public function get(string $url, array $data = []): Response
112112

113113
curl_setopt($this->ch, CURLOPT_HTTPGET, true);
114114

115-
$content = $this->execute();
116-
117-
return new Response($this->ch, $content);
115+
return $this->execute();
118116
}
119117

120118
/**
@@ -158,12 +156,12 @@ private function applyCommonOptions(): void
158156
}
159157

160158
/**
161-
* Execute request
159+
* Execute request and return Response
162160
*
163-
* @return string
161+
* @return Response
164162
* @throws Exception
165163
*/
166-
private function execute(): string
164+
private function execute(): Response
167165
{
168166
if ($this->headers) {
169167
curl_setopt($this->ch, CURLOPT_HTTPHEADER, $this->headers);
@@ -172,6 +170,9 @@ private function execute(): string
172170
$content = curl_exec($this->ch);
173171
$errno = curl_errno($this->ch);
174172

173+
// Create response before closing to capture curl info
174+
$response = new Response($this->ch, $content !== false ? $content : null);
175+
175176
$this->close();
176177

177178
if ($content === false) {
@@ -181,17 +182,40 @@ private function execute(): string
181182
);
182183
}
183184

184-
return $content;
185+
return $response;
185186
}
186187

187188
/**
188-
* Close connection
189+
* Close connection and reset state
189190
*
190191
* @return void
191192
*/
192193
private function close(): void
193194
{
194-
curl_close($this->ch);
195+
$this->ch = null;
196+
$this->headers = [];
197+
$this->attach = [];
198+
$this->accept_json = false;
199+
}
200+
201+
/**
202+
* Send request with custom HTTP method
203+
*
204+
* @param string $method
205+
* @param string $url
206+
* @param array $data
207+
* @return Response
208+
* @throws Exception
209+
*/
210+
private function sendWithMethod(string $method, string $url, array $data = []): Response
211+
{
212+
$this->init($url);
213+
$this->addFields($data);
214+
$this->applyCommonOptions();
215+
216+
curl_setopt($this->ch, CURLOPT_CUSTOMREQUEST, $method);
217+
218+
return $this->execute();
195219
}
196220

197221
/**
@@ -221,9 +245,7 @@ public function post(string $url, array $data = []): Response
221245

222246
curl_setopt($this->ch, CURLOPT_POST, true);
223247

224-
$content = $this->execute();
225-
226-
return new Response($this->ch, $content);
248+
return $this->execute();
227249
}
228250

229251
/**
@@ -257,15 +279,7 @@ private function addFields(array $data): void
257279
*/
258280
public function put(string $url, array $data = []): Response
259281
{
260-
$this->init($url);
261-
$this->addFields($data);
262-
$this->applyCommonOptions();
263-
264-
curl_setopt($this->ch, CURLOPT_CUSTOMREQUEST, "PUT");
265-
266-
$content = $this->execute();
267-
268-
return new Response($this->ch, $content);
282+
return $this->sendWithMethod("PUT", $url, $data);
269283
}
270284

271285
/**
@@ -278,15 +292,60 @@ public function put(string $url, array $data = []): Response
278292
*/
279293
public function delete(string $url, array $data = []): Response
280294
{
295+
return $this->sendWithMethod("DELETE", $url, $data);
296+
}
297+
298+
/**
299+
* Make PATCH request
300+
*
301+
* @param string $url
302+
* @param array $data
303+
* @return Response
304+
* @throws Exception
305+
*/
306+
public function patch(string $url, array $data = []): Response
307+
{
308+
return $this->sendWithMethod("PATCH", $url, $data);
309+
}
310+
311+
/**
312+
* Make HEAD request (retrieves headers only, no body)
313+
*
314+
* @param string $url
315+
* @param array $data
316+
* @return Response
317+
* @throws Exception
318+
*/
319+
public function head(string $url, array $data = []): Response
320+
{
321+
if (count($data) > 0) {
322+
$url = $url . "?" . http_build_query($data);
323+
}
324+
281325
$this->init($url);
282-
$this->addFields($data);
283326
$this->applyCommonOptions();
284327

285-
curl_setopt($this->ch, CURLOPT_CUSTOMREQUEST, "DELETE");
328+
curl_setopt($this->ch, CURLOPT_NOBODY, true);
329+
curl_setopt($this->ch, CURLOPT_CUSTOMREQUEST, "HEAD");
330+
331+
return $this->execute();
332+
}
333+
334+
/**
335+
* Make OPTIONS request (retrieves allowed HTTP methods)
336+
*
337+
* @param string $url
338+
* @return Response
339+
* @throws Exception
340+
*/
341+
public function options(string $url): Response
342+
{
343+
$this->init($url);
344+
$this->applyCommonOptions();
286345

287-
$content = $this->execute();
346+
curl_setopt($this->ch, CURLOPT_CUSTOMREQUEST, "OPTIONS");
288347

289-
return new Response($this->ch, $content);
348+
return $this->execute();
290349
}
291350

292351
/**

tests/Support/HttpClientTest.php

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,64 @@ public function test_delete_method()
102102
$this->assertEquals(200, $response->statusCode());
103103
}
104104

105+
// ==================== PATCH Method Tests ====================
106+
107+
public function test_patch_method_with_data()
108+
{
109+
$http = new HttpClient();
110+
$response = $http->patch("https://httpbin.org/patch", [
111+
'name' => 'patched',
112+
'value' => 'example'
113+
]);
114+
115+
$this->assertEquals(200, $response->statusCode());
116+
$this->assertStringContainsString('patched', $response->getContent());
117+
}
118+
119+
public function test_patch_method_with_json_data()
120+
{
121+
$http = new HttpClient();
122+
$http->acceptJson();
123+
124+
$response = $http->patch("https://httpbin.org/patch", [
125+
'name' => 'patched',
126+
'value' => 'json-example'
127+
]);
128+
129+
$this->assertEquals(200, $response->statusCode());
130+
$this->assertStringContainsString('json-example', $response->getContent());
131+
}
132+
133+
// ==================== HEAD Method Tests ====================
134+
135+
public function test_head_method()
136+
{
137+
$http = new HttpClient();
138+
$response = $http->head("https://httpbin.org/get");
139+
140+
$this->assertEquals(200, $response->statusCode());
141+
// HEAD should not return body content
142+
$this->assertEmpty($response->getContent());
143+
}
144+
145+
public function test_head_method_with_query_params()
146+
{
147+
$http = new HttpClient();
148+
$response = $http->head("https://httpbin.org/get", ['key' => 'value']);
149+
150+
$this->assertEquals(200, $response->statusCode());
151+
}
152+
153+
// ==================== OPTIONS Method Tests ====================
154+
155+
public function test_options_method()
156+
{
157+
$http = new HttpClient();
158+
$response = $http->options("https://httpbin.org/get");
159+
160+
$this->assertEquals(200, $response->statusCode());
161+
}
162+
105163
// ==================== Header Tests ====================
106164

107165
public function test_add_multiple_headers()

0 commit comments

Comments
 (0)