https://github.com/bedrockstreaming/guzzlehttpbundle
Symfony bundle on top of Guzzle
https://github.com/bedrockstreaming/guzzlehttpbundle
http php symfony-bundle
Last synced: 7 months ago
JSON representation
Symfony bundle on top of Guzzle
- Host: GitHub
- URL: https://github.com/bedrockstreaming/guzzlehttpbundle
- Owner: BedrockStreaming
- License: mit
- Created: 2015-06-18T13:49:31.000Z (over 10 years ago)
- Default Branch: master
- Last Pushed: 2024-02-20T14:31:08.000Z (almost 2 years ago)
- Last Synced: 2025-06-19T21:07:05.946Z (7 months ago)
- Topics: http, php, symfony-bundle
- Language: PHP
- Homepage:
- Size: 190 KB
- Stars: 17
- Watchers: 49
- Forks: 10
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- License: LICENSE
- Codeowners: .github/CODEOWNERS
Awesome Lists containing this project
README
# GuzzleHttpBundle
[](https://github.com/BedrockStreaming/GuzzleHttpBundle/actions/workflows/ci.yml) [](https://packagist.org/packages/m6web/guzzle-http-bundle) [](https://packagist.org/packages/m6web/guzzle-http-bundle) [](https://packagist.org/packages/m6web/guzzle-http-bundle) [](https://packagist.org/packages/m6web/guzzle-http-bundle)
The GuzzleHttpBundle provide Guzzle clients as Symfony services.
## Installation
Require the bundle with Composer:
```bash
$ composer require m6web/guzzle-http-bundle
```
> For older Symfony versions, you can try to install an older version of this bundle.
If you don't use Symfony Flex, register the bundle in your kernel:
```php
return [
// ...
M6Web\Bundle\GuzzleHttpBundle\M6WebGuzzleHttpBundle => ['all' => true],
]
```
## Usage
Add the `m6web_guzzlehttp` section in your configuration file. Here is the minimal configuration required.
```yaml
# app/config/config.yml
m6web_guzzlehttp:
clients:
default: ~
other:
base_uri: "http://domain.tld/"
```
All subkey under clients defines an instance of guzzle http client. These services are named `m6web_guzzlehttp_`+subkey expect for the
`default` subkey that define the main service `m6web_guzzlehttp`.
Then you can ask container for your client:
```php
// in a controller
$client = $this->get('m6web_guzzlehttp'); // default client
try {
$response = $client->get('http://domain.tld/path/to/resource');
$promises = [
'first' => $client->getAsync('http://domain.tld/path/to/resource'),
'second' => $client->getAsync('http://domain.tld/path/to/other/resource')
];
$result = \GuzzleHttp\Promise\Utils::unwrap($promises);
} catch(\GuzzleHttp\Exception\ConnectException $e) {
// connection problem like timeout
}
// use other client
$otherClient = $this->get('m6web_guzzlehttp_other');
$response = $otherClient->get('path/to/resource'); // call http://domain.tld/path/to/resource
```
The service return a configured guzzle client, for more information on how to use it, you can read the [guzzle6 documentation](http://guzzle.readthedocs.org/en/latest/index.html).
The only difference with guzzle6 reside in usage of curl for the redirect responses. You can choose to have the guzzle behavior
for redirection by setting the configuration key `redirect_handler` to `guzzle`.
When a cache system is available, you can use `cache_force` and `cache_ttl` in addition of guzzle options than respectively
force clear cache before request and use a specific ttl to a request that override configuration.
```php
$client = $this->get('m6web_guzzlehttp');
$response = $client->get('http://domain.tld', ['cache_force' => true]); // remove cache entry and set a new one
$response = $client->get('http://doamin.tld/path', ['cache_ttl' => 200]); // set ttl to 200 seconds instead the default one
```
## DataCollector
A data collector is available when the Symfony profiler is enabled.
It allows you to inspect the following data:
- Method
- Url
- Response code and reason
- Execution time
- Redirect count
- Redirect time
- Cache hit
- Cache TTL
**NOTE:** If you choose Guzzle for `redirect_handler`, The redirect count and redirect time will always be zero.
Cache information are available when a cache system is set.
## Cache system
You can set a cache for request by adding in the config the `guzzlehttp_cache` with `service` subkey who is a reference
to a service implementing `M6Web\Bundle\GuzzleHttpBundle\Cache\CacheInterface`
```yaml
# app/config/config.yml
m6web_guzzlehttp:
clients:
default:
base_uri: "http://domain.tld/"
guzzlehttp_cache:
service: my_cache_service
```
We provide an "In memory" cache class that you can use by defining a new cache service and use it in Guzzle configuration:
```yaml
# app/config/config.yml
services:
company.guzzle.cache.inmemory:
class: M6Web\Bundle\GuzzleHttpBundle\Cache\InMemory
m6web_guzzlehttp:
clients:
default:
guzzlehttp_cache:
service: company.guzzle.cache.inmemory
```
We also provide a cache interface for Redis with [our RedisBundle](https://github.com/M6Web/RedisBundle) >= 2.4, than you can use in this way:
```yaml
# app/config/config.yml
m6web_guzzlehttp:
clients:
default:
base_uri: "http://domain.tld/"
guzzlehttp_cache:
service: m6_redis.guzzlehttp
m6_redis:
servers:
default:
ip: '127.0.0.1'
port: 6379
clients:
guzzlehttp:
servers: ["default"] # list of servers to use
namespace: GuzzleHttp\
timeout: 2 # timeout in second
readwritetimeout: 2 # read-write timeout in second
class: M6Web\Bundle\RedisBundle\CacheAdapters\M6WebGuzzleHttp
```
For more information on how to set up the RedisBundle, refer to the README in the project.
We provide also the same cache system for APCU through the [ApcuBundle](https://github.com/M6Web/ApcuBundle).
## Configuration reference
As some configuration options accept multiples data types, all services references must start with a `@` character.
```yaml
m6web_guzzlehttp:
clients_share_the_same_handler: false # Use "true" if you want all your clients to share the same Guzzle handler. It means that your different clients will be able to send asynchronous requests altogether.
clients:
default:
base_uri: "" # Base uri to prepend on request uri
timeout: 5.0 # request timeout
http_errors: true # Use "false" to disable throwing exceptions on HTTP protocol errors
redirect_handler: curl # guzzle or curl
guzzlehttp_cache: # optional cache
cache_server_errors: true # at false, no server errors will be cached
cache_client_errors: true # at false, no client errors will be cached
default_ttl: 3600 # default ttl for cache entry in seconds
ignore_cache_errors: false # if true, no exception would be thrown when cache is unavailable
use_header_ttl: false # use the cache-control header to set the ttl
service: '@my_cache_service' # reference to service who implements the cache interface
headers: # optional. Default request headers
User_Agent: "m6web/1.0" # set header "User-Agent" with the value "m6web/1.0"
header\_name: "my value" # set header "header_name" with value "my value"
auth: ["user", "password"] # optional, http auth user and password
allow_redirects: # false to disallow redirection or an array describing the redirect behavior of a request
max: 5 # Maximum redirect to follow
strict: false # use "strict" RFC compliant redirects. (guzzle redirect handler only)
referer: true # add a Referer header
protocols: ['http', 'https'] # restrict redirect to a protocol
body: '@my.body.service' # string | service reference, request body
cert: ['/path/to/.pem', 'password'] # string | array, Set to a string to specify client side certificate, an array if a password is required
cookies: # boolean | array, false disable cookies
-
name: "bar"
value: "foo"
domain: "foobar.com"
path: "/my/path"
max: 100
expires: null
secure: false
discard: false
httpOnly: false
max-age: null
-
name: tracker
value: tracker
connect_timeout: 1 # float, Float describing the number of seconds to wait while trying to connect to a server
debug: true # boolean, Set to true to enable debug output with the handler used to send a request
decode_content: true # string | boolean, specify whether Content-Encoding responses are automatically decoded
delay: 10 # boolean | float, the number of milliseconds to delay before sending the request
expect: true # boolean | integer, controls the behavior of the "Expect: 100-Continue" header
force_ip_resolve: # Set to "v4" if you want the HTTP handlers to use only ipv4 protocol or "v6" for ipv6 protocol.
form_params: # array, Used to send an application/x-www-form-urlencoded POST request.
foo: 'bar'
bar: 'foo'
json: [ foo: 'bar' ] # mixed, the json option is used to easily upload JSON encoded data as the body of a request
multipart: # array, Sets the body of the request to a multipart/form-data form.
-
name: 'foo'
contents: 'bar'
headers:
X-foo: 'bar'
X-bar: 'foo'
on_headers: '@invokable.service.id' # A callable that is invoked when the HTTP headers of the response have been received
on_stats: '@invokable.service.id' # on_stats allows you to get access to transfer statistics
proxy: # string | array, Pass a string to specify an HTTP proxy, or an array to specify different proxies for different protocols.
http: 'tcp://localhost:8125'
query: # array, Associative array of query string values or query string to add to the request.
foo: 'bar'
bar: 'foo'
sink: '/path/to/file' # String or Psr\Http\Message\StreamInterface service, Specify where the body of a response will be saved.
ssl_key: ['/path/to/.pem', 'password'] # string | array, Specify the path to a file containing a private SSL key in PEM format.
stream: true # Boolean, Set to true to stream a response rather than download it all up-front.
synchronous: true # Boolean, Set to true to inform HTTP handlers that you intend on waiting on the response. This can be useful for optimizations.
verify: true # Boolean Describes the SSL certificate verification behavior of a request.
version: 1.0 # String Protocol version to use with the request.
otherclient:
...
```
For the `headers` options, the key in array represent the header name. The underscore will be transformed to hyphen except if it's escaped by a backslash.
## Adding a middleware
Implement `M6Web\Bundle\GuzzleHttpBundle\Middleware\MiddlewareInterface`.
Tag your service with `m6web_guzzlehttp.middleware` and specify the client as follows:
```
Acme\Infra\GraphQL\Client\MyMiddleware:
tags:
- {name: 'm6web_guzzlehttp.middleware', client: 'myclient' }
```
## Contributing
First, thank you for contributing!
Here are few rules to follow for an easier code review before the maintainers accept and merge your pull request:
- you MUST write or update tests
- you MUST write or update documentation
- the CI must pass on your pull request
## Running the test
Install the composer dev dependencies
```shell
make install
```
Then run the test with [atoum](https://github.com/atoum/atoum) unit test framework
```shell
make test
```