Nhảy tới nội dung

HTTP Client

HTTP Client được xây dựng trên Swoole Coroutine HTTP Client, hỗ trợ async requests với hiệu năng cao.

Sử dụng cơ bản

use Vietiso\Core\HttpClient\Facade\Http;

// GET request
$response = Http::get('https://api.example.com/users');

// POST request
$response = Http::post('https://api.example.com/users', [
'name' => 'John',
'email' => 'john@example.com',
]);

// PUT request
$response = Http::put('https://api.example.com/users/1', [
'name' => 'John Doe',
]);

// DELETE request
$response = Http::delete('https://api.example.com/users/1');

// PATCH request
$response = Http::patch('https://api.example.com/users/1', [
'status' => 'active',
]);

// HEAD request
$response = Http::head('https://api.example.com/users');

Response

$response = Http::get('https://api.example.com/users');

// Status code
$status = $response->status();

// Kiểm tra status
$response->ok(); // 200
$response->created(); // 201
$response->accepted(); // 202
$response->noContent(); // 204
$response->movedPermanently(); // 301
$response->found(); // 302
$response->redirect(); // 3xx
$response->badRequest(); // 400
$response->unauthorized(); // 401
$response->paymentRequired(); // 402
$response->forbidden(); // 403
$response->notFound(); // 404
$response->requestTimeout(); // 408
$response->conflict(); // 409
$response->unprocessableEntity(); // 422
$response->tooManyRequests(); // 429
$response->clientError(); // 4xx
$response->serverError(); // 5xx
$response->failed(); // 4xx hoặc 5xx
$response->successful(); // 2xx

// Body
$body = $response->body(); // Raw string
$json = $response->json(); // Array
$data = $response->json('data'); // Nested key với dot notation
$obj = $response->object(); // stdClass object
$isJson = $response->isJson(); // Kiểm tra body có phải JSON không
$col = $response->collect(); // Collection
$col = $response->collect('items'); // Collection từ nested key

// Array access
$userId = $response['id'];
$name = $response['user']['name'];

// Cast sang string
echo (string) $response; // tương đương body()

// Headers
$headers = $response->headers();
$contentType = $response->header('Content-Type');

Throw Exception

// Ném RequestException nếu response là 4xx hoặc 5xx
$response = Http::get('https://api.example.com/users')->throw();

// Ném exception có điều kiện
$response = Http::get('https://api.example.com/users')
->throwIf($response->serverError());

Headers

// Thêm header
$response = Http::withHeader('X-Custom-Header', 'value')
->get('https://api.example.com');

// Nhiều headers
$response = Http::withHeaders([
'X-First' => 'foo',
'X-Second' => 'bar',
])->get('https://api.example.com');

// Replace tất cả headers
$response = Http::replaceHeaders([
'Content-Type' => 'application/json',
])->post('https://api.example.com', $data);

Authentication

// Bearer Token
$response = Http::withToken('your-api-token')
->get('https://api.example.com/users');

// Basic Auth
$response = Http::withBasicAuth('username', 'password')
->get('https://api.example.com/users');

// API Key
$response = Http::withApiKey('your-api-key')
->get('https://api.example.com/users');

Content Types

// JSON (default)
$response = Http::asJson()
->post('https://api.example.com/users', ['name' => 'John']);

// Form data
$response = Http::asForm()
->post('https://api.example.com/users', ['name' => 'John']);

// Accept header
$response = Http::accept('application/json')
->get('https://api.example.com/users');

$response = Http::acceptJson()
->get('https://api.example.com/users');

Base URL

// Set base URL
$response = Http::baseUrl('https://api.example.com')
->get('/users'); // => https://api.example.com/users

$response = Http::baseUrl('https://api.example.com')
->post('/users', $data);

Query Parameters

// URL với query params
$response = Http::get('https://api.example.com/users?page=1&limit=10');

// Hoặc dùng withParams
$response = Http::withParams(['page' => 1, 'limit' => 10])
->get('https://api.example.com/users');

Timeout

// Timeout cho request (giây)
$response = Http::timeout(30)
->get('https://api.example.com/users');

// Connect timeout
$response = Http::connectTimeout(5)
->get('https://api.example.com/users');

// Cả hai
$response = Http::timeout(30)
->connectTimeout(5)
->get('https://api.example.com/users');

Retry

// Thử lại tối đa 3 lần nếu request thất bại
$response = Http::retry(3)
->get('https://api.example.com/users');

// Thử lại 3 lần, delay 500ms giữa mỗi lần
$response = Http::retry(3, 500)
->get('https://api.example.com/users');

File Upload

$response = Http::attach('avatar', '/path/to/image.jpg', 'image/jpeg', 'avatar.jpg')
->post('https://api.example.com/upload');

// Multiple files
$response = Http::attach('file1', '/path/to/file1.pdf')
->attach('file2', '/path/to/file2.pdf')
->post('https://api.example.com/upload');

Redirects

// Cho phép redirect
$response = Http::allowRedirect()
->get('https://example.com/redirect');

// Với options
$response = Http::allowRedirect(
max: 5, // Max redirects
strict: false, // Strict mode
referer: true, // Send referer header
protocols: ['http', 'https'],
trackRedirects: true
)->get('https://example.com/redirect');

// Callback on redirect
$response = Http::allowRedirect()
->onRedirect(function ($response, $location) {
Log::info("Redirecting to: {$location}");
})
->get('https://example.com/redirect');

HTTP/2

$response = Http::withVersion(2.0)
->get('https://api.example.com/users');

// HTTP/1.0
$response = Http::withVersion(1.0)
->get('https://api.example.com/users');

// File upload với HTTP/2 (được hỗ trợ)
$response = Http::withVersion(2.0)
->attach('avatar', '/path/to/image.jpg', 'image/jpeg', 'avatar.jpg')
->post('https://api.example.com/upload');

Connection Pool

use Vietiso\Core\Pool\PoolOptionInterface;

// Đăng ký pool
Http::pool('api-pool', [
'size' => 10,
// ... pool options
]);

// Lấy connection từ pool
$http = Http::pool('api-pool');
$response = $http->get('https://api.example.com/users');

Ví dụ thực tế

Gọi External API

class PaymentGateway
{
protected string $baseUrl = 'https://api.payment.com/v1';
protected string $apiKey;

public function __construct()
{
$this->apiKey = config('services.payment.api_key');
}

public function charge(array $data): array
{
$response = Http::baseUrl($this->baseUrl)
->withToken($this->apiKey)
->timeout(30)
->post('/charges', $data);

if ($response->failed()) {
throw new PaymentException($response->json('error.message'));
}

return $response->json();
}

public function getTransaction(string $id): array
{
return Http::baseUrl($this->baseUrl)
->withToken($this->apiKey)
->get("/transactions/{$id}")
->json();
}
}

Webhook Service

class WebhookService
{
public function send(string $url, array $payload): bool
{
$response = Http::timeout(10)
->asJson()
->post($url, $payload);

return $response->successful();
}
}

API Wrapper

class GitHubApi
{
public function __construct(protected string $token) {}

protected function client(): Http
{
return Http::baseUrl('https://api.github.com')
->withToken($this->token)
->acceptJson();
}

public function getUser(string $username): array
{
return $this->client()
->get("/users/{$username}")
->json();
}

public function getRepositories(string $username): array
{
return $this->client()
->get("/users/{$username}/repos")
->json();
}
}