Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 84 additions & 25 deletions src/Http/Client/HttpClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,7 @@ public function get(string $url, array $data = []): Response

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

$content = $this->execute();

return new Response($this->ch, $content);
return $this->execute();
}

/**
Expand Down Expand Up @@ -158,12 +156,12 @@ private function applyCommonOptions(): void
}

/**
* Execute request
* Execute request and return Response
*
* @return string
* @return Response
* @throws Exception
*/
private function execute(): string
private function execute(): Response
{
if ($this->headers) {
curl_setopt($this->ch, CURLOPT_HTTPHEADER, $this->headers);
Expand All @@ -172,6 +170,9 @@ private function execute(): string
$content = curl_exec($this->ch);
$errno = curl_errno($this->ch);

// Create response before closing to capture curl info
$response = new Response($this->ch, $content !== false ? $content : null);

$this->close();

if ($content === false) {
Expand All @@ -181,17 +182,40 @@ private function execute(): string
);
}

return $content;
return $response;
}

/**
* Close connection
* Close connection and reset state
*
* @return void
*/
private function close(): void
{
curl_close($this->ch);
$this->ch = null;
$this->headers = [];
$this->attach = [];
$this->accept_json = false;
}

/**
* Send request with custom HTTP method
*
* @param string $method
* @param string $url
* @param array $data
* @return Response
* @throws Exception
*/
private function sendWithMethod(string $method, string $url, array $data = []): Response
{
$this->init($url);
$this->addFields($data);
$this->applyCommonOptions();

curl_setopt($this->ch, CURLOPT_CUSTOMREQUEST, $method);

return $this->execute();
}

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

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

$content = $this->execute();

return new Response($this->ch, $content);
return $this->execute();
}

/**
Expand Down Expand Up @@ -257,15 +279,7 @@ private function addFields(array $data): void
*/
public function put(string $url, array $data = []): Response
{
$this->init($url);
$this->addFields($data);
$this->applyCommonOptions();

curl_setopt($this->ch, CURLOPT_CUSTOMREQUEST, "PUT");

$content = $this->execute();

return new Response($this->ch, $content);
return $this->sendWithMethod("PUT", $url, $data);
}

/**
Expand All @@ -278,15 +292,60 @@ public function put(string $url, array $data = []): Response
*/
public function delete(string $url, array $data = []): Response
{
return $this->sendWithMethod("DELETE", $url, $data);
}

/**
* Make PATCH request
*
* @param string $url
* @param array $data
* @return Response
* @throws Exception
*/
public function patch(string $url, array $data = []): Response
{
return $this->sendWithMethod("PATCH", $url, $data);
}

/**
* Make HEAD request (retrieves headers only, no body)
*
* @param string $url
* @param array $data
* @return Response
* @throws Exception
*/
public function head(string $url, array $data = []): Response
{
if (count($data) > 0) {
$url = $url . "?" . http_build_query($data);
}

$this->init($url);
$this->addFields($data);
$this->applyCommonOptions();

curl_setopt($this->ch, CURLOPT_CUSTOMREQUEST, "DELETE");
curl_setopt($this->ch, CURLOPT_NOBODY, true);
curl_setopt($this->ch, CURLOPT_CUSTOMREQUEST, "HEAD");

return $this->execute();
}

/**
* Make OPTIONS request (retrieves allowed HTTP methods)
*
* @param string $url
* @return Response
* @throws Exception
*/
public function options(string $url): Response
{
$this->init($url);
$this->applyCommonOptions();

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

return new Response($this->ch, $content);
return $this->execute();
}

/**
Expand Down
58 changes: 58 additions & 0 deletions tests/Support/HttpClientTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,64 @@ public function test_delete_method()
$this->assertEquals(200, $response->statusCode());
}

// ==================== PATCH Method Tests ====================

public function test_patch_method_with_data()
{
$http = new HttpClient();
$response = $http->patch("https://httpbin.org/patch", [
'name' => 'patched',
'value' => 'example'
]);

$this->assertEquals(200, $response->statusCode());
$this->assertStringContainsString('patched', $response->getContent());
}

public function test_patch_method_with_json_data()
{
$http = new HttpClient();
$http->acceptJson();

$response = $http->patch("https://httpbin.org/patch", [
'name' => 'patched',
'value' => 'json-example'
]);

$this->assertEquals(200, $response->statusCode());
$this->assertStringContainsString('json-example', $response->getContent());
}

// ==================== HEAD Method Tests ====================

public function test_head_method()
{
$http = new HttpClient();
$response = $http->head("https://httpbin.org/get");

$this->assertEquals(200, $response->statusCode());
// HEAD should not return body content
$this->assertEmpty($response->getContent());
}

public function test_head_method_with_query_params()
{
$http = new HttpClient();
$response = $http->head("https://httpbin.org/get", ['key' => 'value']);

$this->assertEquals(200, $response->statusCode());
}

// ==================== OPTIONS Method Tests ====================

public function test_options_method()
{
$http = new HttpClient();
$response = $http->options("https://httpbin.org/get");

$this->assertEquals(200, $response->statusCode());
}

// ==================== Header Tests ====================

public function test_add_multiple_headers()
Expand Down
Loading