m6web / guzzle-http-bundle
Symfony bundle on top of Guzzle
Installs: 487 883
Dependents: 2
Suggesters: 1
Security: 0
Stars: 17
Watchers: 50
Forks: 10
Open Issues: 2
Type:symfony-bundle
Requires
- php: >=8.1
- ext-curl: *
- guzzlehttp/guzzle: ^7
- symfony/config: ^5.4||^6.0
- symfony/dependency-injection: ^5.4||^6.0
- symfony/event-dispatcher: ^5.4||^6.0
- symfony/http-kernel: ^5.4||^6.0
- symfony/yaml: ^5.4||^6.0
Requires (Dev)
- atoum/atoum: 4.2.0
- atoum/stubs: *
- friendsofphp/php-cs-fixer: 3.35.1
- guzzlehttp/promises: ^2
- m6web/php-cs-fixer-config: 3.2.0
- phpstan/phpstan: 1.10.38
- phpstan/phpstan-symfony: 1.3.4
- rector/rector: 0.18.5
- dev-master
- v6.0.0
- v5.1.1
- v5.1.0
- v5.0.4
- v5.0.3
- v5.0.2
- v5.0.1
- v5.0.0
- v4.1.0
- v4.0.1
- v4.0.0
- v3.1.0
- v3.0.2
- v3.0.1
- v3.0.0
- v2.4.2
- v2.4.1
- v2.4.0
- v2.3.0
- v2.2.0
- v2.1.6
- v2.1.5
- v2.1.4
- v2.1.3
- v2.1.2
- v2.1.1
- v2.1.0
- v2.0.2
- v2.0.1
- v2.0.0
- v1.7.0
- v1.6.0
- v1.5.0
- v1.4.8
- v1.4.7
- v1.4.6
- v1.4.5
- v1.4.4
- v1.4.3
- v1.4.2
- v1.4.1
- v1.4.0
- v1.3.2
- v1.3.1
- v1.3.0
- v1.2.0
- v1.1.2
- v1.1.1
- v1.1.0
- v1.0.6
- v1.0.5
- v1.0.4
- v1.0.3
- v1.0.2
- v1.0.1
- v1.0.0
- dev-feat/164623-forward-host-header-from-config-to-request
- dev-fix/empty-body
- dev-feature/add-no-signal-curl-option
- dev-fix/cache-config
This package is auto-updated.
Last update: 2024-10-26 11:33:46 UTC
README
The GuzzleHttpBundle provide Guzzle clients as Symfony services.
Installation
Require the bundle with Composer:
$ 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:
return [ // ... M6Web\Bundle\GuzzleHttpBundle\M6WebGuzzleHttpBundle => ['all' => true], ]
Usage
Add the m6web_guzzlehttp
section in your configuration file. Here is the minimal configuration required.
# 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:
// 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.
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.
$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
# 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:
# 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 >= 2.4, than you can use in this way:
# 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.
Configuration reference
As some configuration options accept multiples data types, all services references must start with a @
character.
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
make install
Then run the test with atoum unit test framework
make test