PHPackages                             pluggit/http-client - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [HTTP &amp; Networking](/categories/http)
4. /
5. pluggit/http-client

ActiveLibrary[HTTP &amp; Networking](/categories/http)

pluggit/http-client
===================

A config-driven library to execute HTTP requests

3.0.0(1y ago)052.8k↓50%1[2 PRs](https://github.com/CMProductions/http-client/pulls)MITPHPPHP ^8.0

Since Oct 31Pushed 3mo ago23 watchersCompare

[ Source](https://github.com/CMProductions/http-client)[ Packagist](https://packagist.org/packages/pluggit/http-client)[ RSS](/packages/pluggit-http-client/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (12)Versions (40)Used By (0)

Pluggit Http
============

[](#pluggit-http)

Small PSR7 compatible library to perform http requests based on pre-configured set of requests

[![Scrutinizer Code Quality](https://camo.githubusercontent.com/f6b1b893116d7a5b8a6e9def6004ba3841e477291dadd5a87539eb3c925ea8b0/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f434d50726f64756374696f6e732f687474702d636c69656e742f6261646765732f7175616c6974792d73636f72652e706e673f623d6d617374657226733d30633666343832633438643037353965663166346232633630313534363962653339383465613062)](https://scrutinizer-ci.com/g/CMProductions/http-client/?branch=master)[![Code Coverage](https://camo.githubusercontent.com/5ffd34a18d61308496a0682b721546bf92fc18e4bae55d496a23c5e1fdc59850/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f434d50726f64756374696f6e732f687474702d636c69656e742f6261646765732f636f7665726167652e706e673f623d6d617374657226733d38313039343837393339393139306635343834343062313633626535623266643965633162313335)](https://scrutinizer-ci.com/g/CMProductions/http-client/?branch=master)[![Build Status](https://camo.githubusercontent.com/c0edea6de19b4edd4c6787fc5af0d6c095eb74e325917a212302d2c28f0e186b/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f434d50726f64756374696f6e732f687474702d636c69656e742f6261646765732f6275696c642e706e673f623d6d617374657226733d34393830623936373236613838613932633361373335356132373062316263313134383230376365)](https://scrutinizer-ci.com/g/CMProductions/http-client/build-status/master)

TL;DR
-----

[](#tldr)

```
# requests.yml
my_cool_api:
  endpoint: http://my_cool_api.com/v2
  requests:
    get_user:
      path: /user/${USER_ID}
    create_user:
      path: /user/${USER_ID}
      method: POST
      headers:
        Content-Type: application/json
      body:
        name: ${NAME}
        email: ${EMAIL}
```

```
$coolApi = ClientBuilder::create()
    ->withYamlConfig('requests.yml')
    ->build('my_cool_api');

$user = $client->json('get_user', ['user_id' => $userId]);

echo "Hello ".$user->name;
```

Table of contents
-----------------

[](#table-of-contents)

- [Installation](#installation)
- [Requirements](#requirements)
    - [Optional requirements](#optional-requirements)
    - [Additional requirements](#additional-requirements)
- [Compatibility](#compatibility)
- [Usage](#usage)
    - [Defining a configuration](#defining-a-configuration)
    - [Building the client](#building-the-client)
    - [Creating a request](#creating-a-request)
    - [Sending the request](#sending-the-request)
    - [Exceptions](#exceptions)
- [REST API integration example](#rest-api-integration-example)
    - [Building the API client](#building-the-api-client)
    - [Get a user](#get-a-user)
    - [Create a user](#create-a-user)
    - [Replace a user](#replace-a-user)
    - [Update a user](#update-a-user)
    - [Delete a user](#delete-a-user)
- [Annexes](#annexes)
    - [Pimple Service Provider](#pimple-service-provider)
    - [Development environment](#development-environment)

Installation
------------

[](#installation)

Require the package as usual

```
composer require pluggit/http-client
```

To use [Guzzle](http://http://docs.guzzlephp.org/en/latest/overview.html) as a sender (the default option), you have to **require it manually**

```
composer require guzzlehttp/guzzle "^6.0"
```

### Requirements

[](#requirements)

- `php >=5.5`
- `guzzlehttp/psr7 ^1.0`
- `psr/log ^1.0`

***Note:*** This package relies on the implementation of guzzle for the [PSR-7: HTTP message interfaces](http://www.php-fig.org/psr/psr-7/)

### Additional requirements

[](#additional-requirements)

#### Guzzle

[](#guzzle)

The library allows to use different senders to execute requests; and adapter for `guzzlehttp/guzzle` it's included in the library **but you must require the dependency manually**

```
composer require guzzlehttp/guzzle "^6.0"
```

### Optional requirements

[](#optional-requirements)

#### Yaml parsing

[](#yaml-parsing)

If you want to use a Yaml file as a configuration source you can: a) Use you own parser and pass the config as an array b) Require `symfony/yaml` as dependency and pass the yaml filepath to the builder

```
composer require symfony/yaml "^3.1"
```

#### Logging

[](#logging)

Do you want to know why your request is failing? No problem, the library accepts any [Psr-3 logger](http://www.php-fig.org/psr/psr-3/) logger implementation (like [Monolog](https://github.com/Seldaek/monolog)) to write debug and error messages.

For a quick start you can use Symfony's console package to have debug messages in the console

```
composer require symfony/console "^3.1"
```

You will now be able to activate the console debug mode

```
$builder->withConsoleDebug();
```

#### Pimple

[](#pimple)

If you use pimple for building your dependencies you can use the provider `Cmp\Http\Provider\HttpClientServiceProvider` to register the [builder](#configuring-the-builder) and the [multi client](#building-a-multi-client).

```
composer require pimple/pimple "^3.0"
```

***NOTE*:** See the annex for how to register the provider
----------------------------------------------------------

[](#note-see-the-annex-for-how-to-register-the-provider)

### Compatibility

[](#compatibility)

This library has been tested with the following PHP versions and setups

PHPguzzlehttp/psr7guzzlehttp/guzzleresult5.5.251.3.16.2.2✅5.6.161.3.16.2.2✅7.0.71.3.16.2.2✅hhvm1.3.16.2.2✅---

Usage
-----

[](#usage)

The library allows to build requests from a set configuration values, execute them trough the client and get a response

### Defining a configuration

[](#defining-a-configuration)

The configuration is what tells the client how to build the requests, let's see some examples of configuration

```
my_users_api:
  endpoint: https://api.mysite.com
  headers:
    api_version: 1.2
  options:
    timeout: 2
  requests:
    list_users:
      path: /users
      options:
        timeout: 15
    get_user:
      path: /users/${USER_ID}
    create_user:
      path: /users/${USER_ID}
      headers:
        - Content-Type: application/json
      method: POST

# Another service
the_comments_api:
  endpoint: http://messaging_service.com/v2/
  ...
```

The first line defines a name for a service, in this case `my_users_api`

**NOTE:** You can see a full-fledged sample configuration file in `config-sample/requests.yaml` for working with a REST API

#### Service configuration values

[](#service-configuration-values)

- `endpoint` (**required**): This is the endpoint for the all the request for this service
- `headers`: A key-value array with the headers to add to *all* the requests for this service
- `query`: A key-value array with the query parameters to append in the URI of *all* the requests for this service
- `body`: A key-value array with the post parameters to send in the body of *all* the requests for this service
- `version`: HTTP protocol version, default one `1.1`
- `options`: A key-value array with options to pass to the http client sender to modify it's behaviour
- `requests`: A key-value array with the allowed requests for this service

#### Request configuration values

[](#request-configuration-values)

The request configuration allows the set almost the same options as the service configuration, overwriting the values provided for the service, this allows to define a general behaviour for a service but tweak some options for specific requests, like for example, allowing a longer timeout

- `path` (**required**): Defines the path that follows the endpoint
- `method`: Defines the HTTP method for the request. `GET` by default
- `headers`: A key-value array with the headers to add to this request
- `query`: A key-value array with the query parameters to append in the URI of this request
- `body`: A key-value array with the post parameters to send in the body of this request
- `version`: HTTP protocol version, default one `1.1`
- `options`: A key-value array with options to pass to the http client sender to modify it's behaviour

##### Underlying client options

[](#underlying-client-options)

The request options allows to customize the client behaviour without the library having to know specific details about how to handle them.

Taking the provided integration with [Guzzle](http://docs.guzzlephp.org/en/latest/request-options.html) as examples, we could have:

- Basic auth: `auth: ['myUser', 'myPass']`
- Timeout: `timeout: 2`
- Connect timeout: `timeout: 15`
- Add a certificate: `['cert' => ['/path/server.pem', 'password']]`

#### Configuration placeholders

[](#configuration-placeholders)

The library allows to indicate the presence of dynamic values in this configuration parameters as placeholders

##### Placeholder rules

[](#placeholder-rules)

- Placeholders are allowed in *path, query, headers* and *body* only
- Use this format to add a placeholder: `${PLACEHOLDER_NAME}`
- Placeholders tag names must be uppercase (although lowercase keys can be used when replacing them)
- You can have the same placeholder multiple times across all options, it will be replaced in all of them.

##### Replacing a placeholder in the request

[](#replacing-a-placeholder-in-the-request)

To replace the placeholders, pass the values as paramters when creating the request

```
secure_api:
  endpoint: https://topsecret.com
  headers:
    api_key: MyPersonalApiKey
    token: ${TOKEN}
  requests:
    get_user:
      path: /users/${USER_ID}
```

```
$request = $client->create('secure_api', 'get_user', [
    'token'   => $oath->sign($secret),
    'user_id' => $userId
]);
```

### Configuring the builder

[](#configuring-the-builder)

The builder (`Cmp\Http\ClientBuilder`) is an object that will help you create you client, easing the customization process. This are the options available:

```
$builder = ClientBuilder::create()
    ->withConfig($requests)
    ->withGuzzleSender($myCustomGuzzleClient)
    ->withConsoleDebug();
```

Once you've configured the builder you're ready to create clients for your http services

### Building the client

[](#building-the-client)

There are 2 different clients that allow to create and execute requests:

- `Cmp\Http\Client\MultiClientInterface`: This client has access to all services
- `Cmp\Http\Client\ServiceClientInterface`: This client can execute request from a single service only

***NOTE***: You *should* try to inject always a `ServiceClientInterface` in your services, this will prevent sideeffects triggering requests from other services by mistake

The available methods in the clients are:

- `create`: Creates a request (`Cmp\Http\Message\Request`)
- `send`: Sends a request returning a `Cmp\Http\Message\Response`

They also provide some shortcuts to ease the use:

- `execute`: Creates and sends a request in a single call
- `json`: Creates and sends a request parsing a json response
- `jsonAsArray`: Creates and sends a request parsing as an array from a json response

#### Building a multi client

[](#building-a-multi-client)

The easiest way to built the client is to use the method `build` on the builder

```
$client = $builder->build();
```

#### Building a service client

[](#building-a-service-client)

To build a service client specify the name of the service when building the client in the last step of the builder

```
$myServiceApi = $builder->build('my_service');
```

#### Customizing the builds

[](#customizing-the-builds)

The client require 3 dependencies to work, the builder has methods to override all of them with custom implementations

##### Sender

[](#sender)

This is the class that sends the requests, it has to implement the `Cmp\Http\Sender\SenderInterface` and return a Psr-7 compatible response

The builder will try to use the provided `Cmp\Http\Sender\GuzzleSender` by default, to specify a different one use:

```
$builder->withSender($sender);
```

Even if you want to use guzzle, ou can also customize the internal client used

```
// tweak the client
$customGuzzleClient = new Guzzlehttp\Guzzle();

// Pass it to the builder
$builder->withGuzzleSender($customGuzzleClient);
```

##### Config

[](#config)

This is the only required dependency, a configuration defining the available the requests

```
$builder->withConfig($config);
```

If `symfony/yaml` is installed, you can pass a filepath with a yaml configuration

```
$builder->withYamlConfig($yamlFile);
```

##### Logger

[](#logger)

You can pass a `Psr\Log\LoggerInterface` to receive debug and error messages

```
$builder->withLogger($logger);
```

If you want to debug the raw http request/responses in the console you can activate the debug output in the builder (You'll need to have `symfony/console` installed)

```
$builder->withConsoleDebug();
```

### Creating a request

[](#creating-a-request)

To create a request you need to identify the service and the request that you want. Additionally you can pass dynamic values to substitute placeholders

```
$request = $client->request('weather', 'forecast', ['city' => $city]);

// Service specific clients do not need the service name
$request = $weather->request('forecast', ['city' => $city]);
```

The requests created are `Cmp\Http\Message\Request` intances, implementing `Psr\Http\Message\RequestInterface`, making them suitable to share between libraries and frameworks

The library request object provides some helpers to work with them in an easier way:

- `withQueryParameter($key, $value)`: Allows you to add or modify a query parameter
- `withPost(array $params)`: Allows to pass a key-value array of params to send as body
- `withJsonPost(array $params)`: Allows to pass a key-value array of params; it will be codified as json and, the header `Content-Type: application/json` will be added
- `__toString()`: This makes the request embeddable in string

#### Customising the request creation

[](#customising-the-request-creation)

If you provide a request factory to the builder that complais with `Cmp\Http\RequestFactoryInterface`, you'll be able to extend the Request class and change the behaviour.

You may ask *"hey, why would I like to do this for?"*

For example to:

- Change all outgoing endpoints to a dummy server to prevent to executed certain requests on test environments
- Apply a configuration to all requests from all services

```
$factory = new TestEnvironmentsRequestFactory($config);
$builder->withRequestFactory($factory);
```

### Sending the request

[](#sending-the-request)

After sending the request you'll receive a `Cmp\Http\Message\Response` instance compatible with `Psr\Http\Message\ResponseInterface`

This response object also provides some helper methods:

- `json($asArray = true)`: Parses the body as a json an returns either a `stdClass` object or an `array`
- `jsonAsArray()`: Same as before, but forcing the return type to be an array
- `__toString()`: This makes the response embeddable in string

### Exceptions

[](#exceptions)

Not everything works as expected; to make your life easier handling this, the library provides a small set of exceptions:

- `Cmp\Http\Exception\RuntimeException`: This is the base exception used in the library, all the exceptions thrown within the library code uses or extends this one
- `Cmp\Http\Exception\RequestBuildException`: This exception is thrown when the process of building a request cannot be completed
- `Cmp\Http\Exception\RequestExecutionException`: This exception is thrown when some error happens sending the request

---

REST API integration example
----------------------------

[](#rest-api-integration-example)

I'm going to show you how to perform the most common operation in a REST API.
Lets imagine that we want to interact with an API endpoint to manage our application users. The user entity looks like:

```
{
  "id": "1",
  "first_name": "John",
  "last_name": "Doe"
}
```

Now let's define the typical requests in our configuration file

```
# Service definition
my_app:
  # The endpoint is required
  endpoint: https://api.myapp.com/v1
  options:
    auth: ['apikey', 'secret']

  # At least one request is required too
  requests:
    list_users:
      path: /users

    get_user:
      path: /users/${USER_ID}

    delete_user:
      path: /users/${USER_ID}
      method: DELETE

    put_user:
      path: /users/${USER_ID}
      method: PUT
      headers:
        Content-Type: application/json
      body:
        first_name: ${FIRST_NAME}
        last_name: ${LAST_NAME}

    create_user:
      path: /users
      method: POST
      headers:
        Content-Type: application/json
      body:
        first_name: ${FIRST_NAME}
        last_name: ${LAST_NAME}

    update_user:
      path: /users/${USER_ID}
      method: PATCH
      headers:
        Content-Type: application/json
      # body: No need to define all the body params here, we can do it at request time
```

### Building the API client

[](#building-the-api-client)

Let's build a service client for our api, as per the configuration, all the requests will include a basic authentication

```
$api = $builder->build('my_app');
```

\###List users This call would return an array of users

```
// We are going to modify the request to pass a limit on the number of users to retrieve
$users = $api->send($api->request('list_users')->withQueryParameter('limit', 25))->json();
```

### Get a user

[](#get-a-user)

This call will inject the user id in the path of the uri to request the user

```
// The json shortcut creates, executes and parses the body response all in a single call
$users = $api->json('get_user', ['user_id => 1]);
```

### Create a user

[](#create-a-user)

Here we're going to replace the placeholders in the body array, if the api only accepts a json body, we have to add the correct content type header, like in the example so the request is created correctly

```
$user = $api->json('create_user', ['name' => 'Jane', 'last_name' => 'Roe']);
```

### Replace a user

[](#replace-a-user)

We can replace placeholders in both path or body params at the same time

```
$user = $api->json('put_user', ['user_id' => 1, 'name' => 'Jane', 'last_name' => 'Roe']);
```

### Update a user

[](#update-a-user)

When we update some fields only, we don't known in advance what fields we are going to send, so it's better to decide later

```
$request = $api->create('update_user', ['user_id' => 1]);
// Remember to assign the result, as the request return always a new instance when modifying it
$request = $request->withPost(['name' => 'Jane']);
$updatedUser = $api->send($request)->json();
```

### Delete a user

[](#delete-a-user)

Deleting a user is even easier

```
$api->execute('delete_user', ['user_id' => 1]);
```

---

Annexes
-------

[](#annexes)

### Pimple Service Provider

[](#pimple-service-provider)

The library includes a service provider for Pimple to register a client in an easy way: `Cmp\Http\Provider\HttpClientServiceProvider`The provider will register the builder `Cmp\Http\ClientBuilder` object at key `http_client.builder` and a general purpouse multi-client `Cmp\Http\Client\MultiClient` in `http_client.client`, but it also accepts alias for both services

```
$container->register(new HttpClientServiceProvider('requester', 'client'), [
    'http_client.yaml' => 'config/requests.yml',
]);
$builder = $container['requester']; // or http_client.builder
$client = $container['client'];     // or http_client.client
```

The options that the provider accepts are:

- `http_client.yaml`: A filepath with a ymal configuration file
- `http_client.config`: A configuration array with the requests
- `http_client.logger`: Pass a Psr\\Logger\\LoggerInterface object to add logging to the client
- `http_client.sender`: A custom implementation of the `Cmp\Http\Sender\SenderInterface` interface
- `http_client.guzzle`: A custom `GuzzleHttp\ClientInterface` object (useful to keep a reference)
- `http_client.factory`: A custom `Cmp\Http\RequestFactoryInterface` implementation
- `http_client.debug`: Pass true and this will activate console output for debugging

---

### Development environment

[](#development-environment)

To build the test environment you'll need docker and docker-compose installed:

```
make dev

```

#### Running the tests

[](#running-the-tests)

```
make unit
make integration
```

You can run the tests only for a php version like this

```
make unit PHP_VERSION=5.6
make integration PHP_VERSION=5.6
```

#### Code-coverage

[](#code-coverage)

You can build a report for code coverage in HTML format. It will be available in `bin/code-coverage`

```
make code-coverage
```

#### Stop the environment

[](#stop-the-environment)

```
make nodev

```

#### Delete the environment

[](#delete-the-environment)

You can delete the docker images for a total clean-up

```
 make nodev IMAGES=true
```

###  Health Score

50

—

FairBetter than 96% of packages

Maintenance58

Moderate activity, may be stable

Popularity27

Limited adoption so far

Community21

Small or concentrated contributor base

Maturity80

Battle-tested with a long release history

 Bus Factor3

3 contributors hold 50%+ of commits

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~111 days

Recently: every ~523 days

Total

26

Last Release

706d ago

Major Versions

1.2.4 → 2.0.02018-09-19

1.2.5 → 3.0.02024-06-12

PHP version history (3 changes)1.0.0PHP &gt;=5.5

2.0.0PHP ^7.1.3

3.0.0PHP ^8.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/2595584d57cbf851b56dc1935d9e34d96045fc7b4ca3c64058caa3ed5e3fb504?d=identicon)[techCMP](/maintainers/techCMP)

---

Top Contributors

[![hmoragrega](https://avatars.githubusercontent.com/u/3494001?v=4)](https://github.com/hmoragrega "hmoragrega (10 commits)")[![martamoraguesteamcmp](https://avatars.githubusercontent.com/u/28294561?v=4)](https://github.com/martamoraguesteamcmp "martamoraguesteamcmp (6 commits)")[![AaronBernabeu](https://avatars.githubusercontent.com/u/3294776?v=4)](https://github.com/AaronBernabeu "AaronBernabeu (6 commits)")[![danielmartincmp](https://avatars.githubusercontent.com/u/24294532?v=4)](https://github.com/danielmartincmp "danielmartincmp (5 commits)")[![marcrubiocmp](https://avatars.githubusercontent.com/u/17856285?v=4)](https://github.com/marcrubiocmp "marcrubiocmp (4 commits)")[![amavica-mad](https://avatars.githubusercontent.com/u/19685680?v=4)](https://github.com/amavica-mad "amavica-mad (3 commits)")[![jmartinmad](https://avatars.githubusercontent.com/u/17850794?v=4)](https://github.com/jmartinmad "jmartinmad (2 commits)")[![jaroslawgabaracmp](https://avatars.githubusercontent.com/u/20397078?v=4)](https://github.com/jaroslawgabaracmp "jaroslawgabaracmp (2 commits)")[![joangoat](https://avatars.githubusercontent.com/u/39056218?v=4)](https://github.com/joangoat "joangoat (1 commits)")[![joancmp](https://avatars.githubusercontent.com/u/25739876?v=4)](https://github.com/joancmp "joancmp (1 commits)")[![sabineCMP](https://avatars.githubusercontent.com/u/19949511?v=4)](https://github.com/sabineCMP "sabineCMP (1 commits)")

---

Tags

orphan

###  Code Quality

TestsBehat

### Embed Badge

![Health badge](/badges/pluggit-http-client/health.svg)

```
[![Health](https://phpackages.com/badges/pluggit-http-client/health.svg)](https://phpackages.com/packages/pluggit-http-client)
```

###  Alternatives

[shopify/shopify-api

Shopify API Library for PHP

4634.8M16](/packages/shopify-shopify-api)[api-platform/metadata

API Resource-oriented metadata attributes and factories

243.5M96](/packages/api-platform-metadata)[gmponos/guzzle_logger

A Guzzle middleware to log request and responses automatically

772.2M6](/packages/gmponos-guzzle-logger)[phpro/http-tools

HTTP tools for developing more consistent HTTP implementations.

28137.8k](/packages/phpro-http-tools)[mimmi20/browser-detector

Library to detect Browsers and Devices

48153.5k3](/packages/mimmi20-browser-detector)[discord-php/http

Handles HTTP requests to Discord servers

25318.7k8](/packages/discord-php-http)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
