lucinda/requester

Light weight complete object oriented cURL wrapper for HTTP/HTTPS requests

v2.0.8 2024-10-30 09:29 UTC

README

Table of contents:

About

This API is a light weight cURL wrapper aimed at completely hiding chaotic native library underneath through a full featured OOP layer that is easy and logical to work with. It is built as an antithesis of Guzzle, the "industry standard" today, by being:

  • self-reliant: unlike Guzzle, which has no less than 40 dependencies, it depends only on 1 library for unit testing
  • very simple: each class is designed to cover an aspect of a URL request and response processing, but only a limited number are relevant for developers
  • very fast: all code inside is developed on "less is more" paradigm: no over abstraction, no line of code more than strictly needed

Library is 99% unit tested (some areas of cURL functionality have zero documentation), fully PSR-4 compliant, only requiring PHP8.1+ interpreter and cURL extension. For installation you just need to write this in console:

composer require lucinda/requester

Then use one of main classes provided:

Each of above classes branches through its methods to deeper classes that become relevant depending on the complexity of request. The end result of every request is a Lucinda\URL\Response object, encapsulating all response information (headers, body, status).

Running single requests

Performing a single HTTPs request is as simple as this:

$request = new Lucinda\URL\Request("https://www.lucinda-framework.com");
$response = $request->execute();

This automatically sends target host embedded CAINFO certificate along with URL in order to establish a TLS connection then receives a Lucinda\URL\Response object. The class in charge of single requests is Lucinda\URL\Request, defining following public methods:

File Uploading

API comes with Lucinda\URL\Request extensions specifically designed for file upload. To upload a file you must use Lucinda\URL\FileUpload, which comes with following additional public methods:

Example (uploads LOCAL_FILE_PATH to REMOTE_FILE_PATH):

$request = new Lucinda\URL\FileUpload(REMOTE_FILE_PATH);
$request->setMethod(Lucinda\URL\Request\Method::PUT);
$request->setFile(LOCAL_FILE_PATH);
$request->execute();

File Downloading

API comes with Lucinda\URL\Request extensions specifically designed for file download. To download a file you must use Lucinda\URL\FileDownload, which comes with following additional public methods:

Example (downloads REMOTE_FILE_PATH into LOCAL_FILE_PATH):

$request = new Lucinda\URL\FileDownload(REMOTE_FILE_PATH);
$request->setMethod(Lucinda\URL\Request\Method::GET);
$request->setFile(LOCAL_FILE_PATH);
$request->execute();

Running multiple asynchronous requests

Performing multiple requests at once it is no less simple:

$multiRequest = new Lucinda\URL\MultiRequest(Lucinda\URL\Request\Pipelining::HTTP2);
$multiRequest->add(new Lucinda\URL\Request("https://www.lucinda-framework.com/news"));
$multiRequest->add(new Lucinda\URL\Request("https://www.lucinda-framework.com/tutorials"));
$responses = $multiRequest->execute();

This executes two requests simultaneously using HTTP2 pipelining and receives a Response object array. The class in charge of single requests is Lucinda\URL\MultiRequest, defining following public methods:

Unlike native curl_multi, responses will be received in the order requests were pooled! Execution will be performed depending on pipelining option (see constructor):

  • DISABLED: connections are not pipelined
  • HTTP1: attempts to pipeline HTTP/1.1 requests on connections that are already established
  • HTTP2: attempts to multiplex the new transfer over an existing connection if HTTP/2
  • HTTP1_HTTP2: attempts pipelining and multiplexing independently of each other

Running cookie sharing synchronous requests

To make multiple requests share cookies/dns, it is as simple as:

$sharedRequest = new Lucinda\URL\SharedRequest(Lucinda\URL\Request\ShareType::COOKIE);
$request1 = new Lucinda\URL\Request("http://www.example.com/page1");
$multiRequest->add($request1);
$request2 = new Lucinda\URL\Request("http://www.example.com/page1");
$multiRequest->add($request2);
$response1 = $request1->execute();
$response2 = $request2->execute();

This very poorly documented feature makes 2nd request able to see cookies in first request. The class in charge of cookie-sharing requests is Lucinda\URL\SharedRequest, defining following public methods:

Unlike the other two classes of running requests, each request must be executed manually in order to produce a response! Cookie sharing will be performed depending on share type option (see constructor):

  • COOKIES: connections will share HTTP cookies
  • DNS: connections will share cached DNS hosts
  • SSL_SESSION: connections will share SSL session IDs

Working with HTTP cookies

API comes with a number of classes for working with cookies, whose area is IN BETWEEN requests and responses:

They are rarely needed in everyday usage, so for more info click on their links to see documentation. To see how they can be used, please check respective unit tests!

Working with responses

The end result of every successful request (defined as one that received ANY response) is encapsulated into a Lucinda\URL\Response object that includes:

  • response status: HTTP status that came with response
  • response headers: HTTP headers received along with response
  • response body: actual contents of response (minus headers and status)
  • response statistics: as supplied by API or cURL driver underneath (eg: total duration)

All this information can be queried via following public methods:

Examples

HTTP GET Request

# any request that doesn't *setMethod* is considered GET by default
$request = new Lucinda\URL\Request("https://www.example.com/?id=1");
$response = $request->execute();

HTTP POST Request

# any POST request MUST *setParameters*
$request = new Lucinda\URL\Request("https://www.example.com/add");
$request->setMethod(\Lucinda\URL\Request\Method::POST);
$request->setParameters(["asd"=>"fgh", "qwe"=>"rty"]);
$response = $request->execute();

HTTP PUT Request

# any PUT request MUST *setRaw* AND stringify parameters
$request = new Lucinda\URL\Request("https://www.example.com/edit");
$request->setMethod(\Lucinda\URL\Request\Method::PUT);
$request->setRaw(http_build_query(["id"=>1, "qwe"=>"tyu"]));
$response = $request->execute();

HTTP DELETE Request

# any DELETE request MUST *setRaw* AND stringify parameters
$request = new Lucinda\URL\Request("https://www.example.com/delete");
$request->setMethod(\Lucinda\URL\Request\Method::DELETE);
$request->setRaw(http_build_query(["id"=>1]));
$response = $request->execute();

Error handling

Following exceptions may be thrown during request-response process by this API:

A few observations:

  • No support for curl_share_err errors, for whom there is zero documentation in both PHP cURL documentation as well as the C library it wraps
  • As long as response is received for a request, no exception is thrown! API does not consider statuses such as 404 or 500 to be errors by default, so it is up to developers to decide how to handle them