PHPackages                             mnapoli/bof - 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. mnapoli/bof

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

mnapoli/bof
===========

The HTTP client for humans

0.1.1(5y ago)79204[1 issues](https://github.com/mnapoli/bof/issues)MITPHPPHP &gt;=7.3CI failing

Since Oct 26Pushed 4y ago6 watchersCompare

[ Source](https://github.com/mnapoli/bof)[ Packagist](https://packagist.org/packages/mnapoli/bof)[ RSS](/packages/mnapoli-bof/feed)WikiDiscussions master Synced 3d ago

READMEChangelog (2)Dependencies (7)Versions (3)Used By (0)

The HTTP client for humans.

[![Build Status](https://camo.githubusercontent.com/89c1ed62dc14341e867069847fd3a49d736e5eb6faeaa82dd62c95358b0b0a7a/68747470733a2f2f696d672e736869656c64732e696f2f7472617669732f636f6d2f6d6e61706f6c692f626f662f6d61737465722e7376673f7374796c653d666c61742d737175617265)](https://travis-ci.com/mnapoli/bof)[![Latest Version](https://camo.githubusercontent.com/33013e74682c2ae1bfd77d62db37509fafae88140b7dd018698c2dfc487ebbd7/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f72656c656173652f6d6e61706f6c692f626f662e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/mnapoli/bof)

[![](img/logo.png)](img/logo.png)

Why?
----

[](#why)

Bof is a HTTP client meant to be as user friendly as possible.

It makes the most classic use cases, such as downloading a file, interacting with a JSON API or submitting a form, as simple as possible.

Since Bof is based on [Guzzle](http://docs.guzzlephp.org/en/stable/overview.html), more advanced use cases can be addressed by using Guzzle's methods directly.

To sum up, Bof:

- is user friendly
- avoids magic strings and arrays for configuration: instead it provides explicit, typed and documented methods that can be autocompleted by IDEs
- comes with sane defaults: JSON is supported natively, 4xx and 5xx responses throw exceptions, timeouts are short by default
- is PSR-7 compliant

Future plans:

- PSR-18 compliance (the HTTP client standard)
- resiliency mechanisms such as retry, backoff, etc.

Want a short illustration? Here is Bof compared to Guzzle:

```
// Bof
$http = new Bof\Http;
$createdProduct = $http
    ->withHeader('Authorization', 'Token abcd')
    ->postJson('https://example.com/api/products', [
        'Hello' => 'world',
    ])
    ->getData();

// Guzzle
$client = new GuzzleHttp\Client([
    'headers' => [
        'Authorization' => 'Token abcd',
    ],
]);
$response = $client->request('POST', 'https://example.com/api/products', [
   'json' => [
        'Hello' => 'world',
   ]
]);
$createdProduct = json_decode($response->getBody()->__toString(), true);
if (json_last_error() !== JSON_ERROR_NONE) {
    throw new Exception('There was an error while decoding the JSON response');
}
```

Do we need a new HTTP client?
-----------------------------

[](#do-we-need-a-new-http-client)

Probably not. If this client attracts interest, that may mean that our already popular HTTP clients could use a simpler API targeting the simple use cases. If you maintain a HTTP client and are interested, I would love to merge Bof into existing libraries. Open an issue!

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

[](#installation)

```
composer require mnapoli/bof
```

Usage
-----

[](#usage)

```
$http = new Bof\Http;

$response = $http->get('https://example.com/api/products');
```

### Configuration

[](#configuration)

**The `Bof\Http` class is immutable**.

Configuration is applied by calling `withXxx()` methods which create a new object every time:

```
$http = new Bof\Http;

// The header will apply to all subsequent requests
$http = $http->withHeader('Authorization', "Bearer $token");
```

Remember that `withXxx()` methods return *a copy* of the original client:

```
$http1 = new Bof\Http;

$http2 = $http1->withHeader('Authorization', "Bearer $token");

// $http1 does not have the header applied
// $http2 has the header
```

Thanks to that pattern, the same methods can be used to apply configuration only for a specific request:

```
$products = $http->withHeader('Authorization', "Bearer $token")
    ->get('https://example.com/api/products')
    ->getData();

// The next requests will *not* have the `Authorization` header
```

### Responses

[](#responses)

Responses are PSR-7 compliant. They also provide methods to facilitate working with JSON responses:

```
$http = new Bof\Http;

$products = $http->get('https://example.com/api/products')
    ->getData();
```

The `getData()` method will decode the JSON response.

All PSR-7 methods are also available:

```
$response = $http->get('https://example.com/api/products');
echo $response->getStatusCode();
echo $response->getHeader('Content-Length')[0];
echo $response->getBody()->getContents();
```

[Learn more](http://docs.guzzlephp.org/en/stable/quickstart.html#using-responses).

### Sending JSON data

[](#sending-json-data)

Using the JSON methods, the data will automatically encoded to JSON. A `Content-Type` header of `application/json` will be added.

```
$http->postJson('https://example.com/api/products', [
    'foo' => 'bar',
]);
// putJson() or patchJson() works as well
```

### Sending form data

[](#sending-form-data)

Data can also be sent as a `application/x-www-form-urlencoded` POST request:

```
$http->postForm('https://example.com/api/products', [
    'foo' => 'bar',
    'baz' => ['hi', 'there!'],
]);
// putForm() works as well
```

### Exceptions

[](#exceptions)

Invalid HTTP responses (status code 4xx or 5xx) will throw exceptions.

```
try {
    $http->get('https://example.com/api/products');
} catch (\GuzzleHttp\Exception\GuzzleException $e) {
    // $e->getRequest()
    // $e->getResponse()
    ...
}
```

[Learn more](http://docs.guzzlephp.org/en/stable/quickstart.html#exceptions).

### Headers

[](#headers)

```
$http = $http->withHeader('Authorization', "Bearer $token");

// Headers can have multiple values
$http = $http->withHeader('X-Foo', ['Bar', 'Baz']);
```

### Timeouts

[](#timeouts)

Timeouts are set at short values by default:

- 5 seconds for the request timeout
- 3 seconds for the HTTP connection timeout

You can set shorter or longer timeouts (or disable them by setting them at `0`):

```
// 2 seconds for the request timeout, 1 second for the connection timeout
$http = $http->withTimeout(2, 1);
```

### Query string parameters

[](#query-string-parameters)

You can set query string parameters in the request's URI:

$response = $http-&gt;get('');

You can specify the query string parameters as an array:

```
$http->withQueryParams(['foo' => 'bar'])
    ->get('http://httpbin.org');
```

Providing the option as an array will use PHP's `http_build_query` function to format the query string.

And finally, you can provide the query request option as a string.

```
$http->withQueryParams('foo=bar')
    ->get('http://httpbin.org');
```

### Proxy

[](#proxy)

Use `withSingleProxy()` to specify a proxy for all protocols:

```
$http = $http->withSingleProxy('tcp://localhost:8125');
```

Use `withMultipleProxies()` to specify a different proxy for HTTP and HTTPS, as well as a list of host names that should not be proxied to:

```
$http = $http->withMultipleProxies(
    'tcp://localhost:8125', // Use this proxy with HTTP
    'tcp://localhost:9124', // Use this proxy with HTTPS
    ['.mit.edu', 'foo.com'] // Don't use a proxy with these
);
```

Note that you can provide proxy URLs that contain a scheme, username, and password. For example, `http://username:password@192.168.16.1:10`.

Guzzle integration
------------------

[](#guzzle-integration)

Bof is based on Guzzle. You can even make it use your own Guzzle client, for example if you preconfigured it:

```
$guzzleClient = new GuzzleHttp\Client([
    'base_uri' => 'http://httpbin.org',
    'timeout'  => 2.0,
]);

$http = new Bof\Http($guzzleClient);
```

[Learn more](http://docs.guzzlephp.org/en/stable/request-options.html).

###  Health Score

26

—

LowBetter than 43% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity20

Limited adoption so far

Community14

Small or concentrated contributor base

Maturity44

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 96.3% of commits — single point of failure

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 ~463 days

Total

2

Last Release

1930d ago

PHP version history (2 changes)0.1.0PHP ^7.3

0.1.1PHP &gt;=7.3

### Community

Maintainers

![](https://www.gravatar.com/avatar/329a6111724074f5388e95dd41a03ccf3c43f4bfe1ecf27c94c9efc6f7823228?d=identicon)[mnapoli](/maintainers/mnapoli)

---

Top Contributors

[![mnapoli](https://avatars.githubusercontent.com/u/720328?v=4)](https://github.com/mnapoli "mnapoli (26 commits)")[![peter279k](https://avatars.githubusercontent.com/u/9021747?v=4)](https://github.com/peter279k "peter279k (1 commits)")

---

Tags

guzzlehttphttp-clientphppsr-7httpclienthttp client

###  Code Quality

TestsPHPUnit

Static AnalysisPsalm

Type Coverage Yes

### Embed Badge

![Health badge](/badges/mnapoli-bof/health.svg)

```
[![Health](https://phpackages.com/badges/mnapoli-bof/health.svg)](https://phpackages.com/packages/mnapoli-bof)
```

###  Alternatives

[react/http

Event-driven, streaming HTTP client and server implementation for ReactPHP

78126.4M414](/packages/react-http)[simpod/clickhouse-client

PHP ClickHouse Client

19116.7k](/packages/simpod-clickhouse-client)[amphp/http-client-guzzle-adapter

Guzzle adapter for Amp's HTTP client.

1523.6k1](/packages/amphp-http-client-guzzle-adapter)[m6web/guzzle-http-bundle

Symfony bundle on top of Guzzle

17511.5k2](/packages/m6web-guzzle-http-bundle)[phpro/http-tools

HTTP tools for developing more consistent HTTP implementations.

28137.8k](/packages/phpro-http-tools)[slimpay/hapiclient

An HTTP Client using HAL as the format for resources.

14317.3k](/packages/slimpay-hapiclient)

PHPackages © 2026

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