HTTP Client là gì

Khi ta truy cập một website và tương tác với các thành phần của website để gửi thông tin thì bản chất của việc đó là browser thay ta gửi đi các HTTP requests. Khi đó browser mà chúng ta đang dùng đóng vai trò một HTTP client.

Tạo request với Guzzle - PHP HTTP Client 2

Vòng đời của 1 HTTP request

Không chỉ có browser được đóng vai trò là HTTP client, bất kỳ phần mềm nào có thể gửi HTTP request và nhận được response từ HTTP server thì đều là HTTP client cả.

Tạo request với Guzzle - PHP HTTP Client 3

Nói một cách đơn giản: Bên gửi request là client – bên nhận request là server.

Với PHP, ta có thể viết những đoạn code để request đến server khác. Ứng dụng thực tiễn của PHP HTTP client rất nhiều, ví dụ:

  • Crawl dữ liệu
  • Tương tác với RESTful API
  • Upload file lên S3
  • Đăng nhập OAuth

Tại sao lại là Guzzle

Thuở mới vào nghề, tôi hay dùng file_get_contents, đây là hàm đơn giản nhất để gửi đi một request từ PHP. Tuy nhiên nó có rất nhiều hạn chế khi muốn gửi một request phức tạp.

Khi đã khá khẩm hơn chút, tôi dùng cURL. Thằng này là một thư viện đầy đủ các option để ta có thể gửi những request phức tạp, độ linh động cao. Nhưng thằng này khai báo code quá rườm rà, hơn nữa cURL yêu cầu máy chủ phải cài curl và php-curl để có thể hoạt động.

// create curl resource 
$ch = curl_init(); 

// set url 
curl_setopt($ch, CURLOPT_URL, "example.com"); 

//return the transfer as a string 
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 

// $output contains the output string 
$output = curl_exec($ch); 

// close curl resource to free up system resources 
curl_close($ch);

Khá khẩm hơn một chút nữa, tôi biết dùng composer và xài các thư viện để gửi request thay cho cURL. Thư viện đầu tiên mà tôi xài là Requests của Ryan McCue. Thư viện này có ưu điểm là dễ sử dụng và linh hoạt, ví dụ nếu phát hiện máy chủ chưa cài cURL thì nó sẽ dùng fsockopen. Biết dùng composer là một bước tiến lớn trong sự nghiệp lập trình PHP của tôi.

// Cú pháp của Requests rất ngắn gọn
$headers = array('Accept' => 'application/json');
$options = array('auth' => array('user', 'pass'));
$request = Requests::get('https://api.github.com/gists', $headers, $options);

Cuối cùng là Guzzle. Có kha khá lý do khiến tôi đổi sang dùng Guzzle. Cùng là một composer package nhưng Guzzle mang nhiều ưu điểm về độ tin cậy, độ linh hoạt, cách dùng, tính năng. Thời điểm hiện tại Guzzle có 13k stars trên github. Đã sử dụng thư viện thì mình phải xài cái ngon nhất chứ đúng không  😀 .

// Send an asynchronous request.
$request = new \GuzzleHttp\Psr7\Request('GET', 'http://httpbin.org');
$promise = $client->sendAsync($request)->then(function ($response) {
    echo 'I completed! ' . $response->getBody();
});
$promise->wait();

Cài đặt Guzzle

Vì là một composer package nên bạn phải cài composer và tích hợp composer vào dự án của bạn đã, những framework hiện đại như Symfony và Laravel thì không cần vì chúng đã được tích hợp sẵn rồi. Tiếp theo là dùng lệnh sau để thêm Guzzle vào dự án:

$ composer require guzzlehttp/guzzle

Gửi Request bằng Guzzle

Vì bài viết chỉ mang tính chất quảng cáo cho Guzzle, nên tôi sẽ không đi quá sâu về cách sử dụng nó mà chỉ đưa ra vài ví dụ đơn giản. Mặt khác, khi dùng thư viện thì tốt nhất nên đọc tài liệu chính thống của nó thay vì xem tutorial.

1. Gửi GET request

use GuzzleHttp\Client;

$client = new GuzzleHttp\Client();
$res = $client->request('GET', 'https://httpbin.org/get');

var_dump($res->getStatusCode());
// "200"
var_dump($res->getHeader('content-type'));
// 'application/json; charset=utf8'

var_dump($res->getBody()->getContents());
// {"args":{},'

2. Gửi POST request với form params

$res = $client->request('POST', 'https://httpbin.org/post',[
    'form_params' => [
        'input1' => 'data1',
        'input2' => 'data2',
    ],
]);

3. Basic auth

$res = $client->request('GET', 'https://api.github.com/user', [
    'auth' => ['user', 'pass']
]);

4. Async request

use GuzzleHttp\Client;
use GuzzleHttp\Promise;

$client = new Client(['base_uri' => 'http://httpbin.org/']);

// Initiate each request but do not block
$promises = [
    'image' => $client->getAsync('/image'),
    'png'   => $client->getAsync('/image/png'),
    'jpeg'  => $client->getAsync('/image/jpeg'),
    'webp'  => $client->getAsync('/image/webp')
];

// Wait on all of the requests to complete. Throws a ConnectException
// if any of the requests fail
$results = Promise\unwrap($promises);

// Wait for the requests to complete, even if some of them fail
$results = Promise\settle($promises)->wait();

// You can access each result using the key provided to the unwrap
// function.
echo $results['image']['value']->getHeader('Content-Length')[0]
echo $results['png']['value']->getHeader('Content-Length')[0]

Tổng kết

Life is short, use composer

Việc dùng thư viện sẽ giúp bạn tiết kiệm được kha khá thời giantránh được nhiều lỗi không đáng có. Tuy vậy, nó vẫn có nhược điểm cho nên đừng lạm dụng quá.

Thứ nhất là làm cho bạn phụ thuộc vào thư viện, thứ hai là làm tăng độ cồng kềnh của dự án. Chỉ cần maintainer thư viện đó lỡ tay release một bản lỗi thôi là dự án bạn cũng lỗi theo, hoặc là cả một project của bạn chỉ có một chỗ gọi HTTP GET request đơn giản nhưng bạn lại cài cả một thư viện to uỳnh vào là không cần thiết.

In fact, việc quyết định sử dụng hay không sử dụng thư viện cũng tạo nên sự khác biệt giữa junior và senior đấy. Happy coding!

0 0 votes
Article Rating