From 5ff74f549f557a348d76d3cc6877f235ca5ad217 Mon Sep 17 00:00:00 2001 From: Gary PEGEOT Date: Sun, 31 Mar 2019 22:04:11 +0100 Subject: [PATCH 1/3] Add documentation for the VCR plugin --- plugins/index.rst | 1 + plugins/vcr.rst | 96 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 plugins/vcr.rst diff --git a/plugins/index.rst b/plugins/index.rst index 7a08d49..530d1e8 100644 --- a/plugins/index.rst +++ b/plugins/index.rst @@ -26,3 +26,4 @@ request or you can even start a completely new request. This gives you full cont request-uri-manipulations retry stopwatch + vcr diff --git a/plugins/vcr.rst b/plugins/vcr.rst new file mode 100644 index 0000000..9c19c66 --- /dev/null +++ b/plugins/vcr.rst @@ -0,0 +1,96 @@ +VCR Plugin +========== + +The VCR plugins allow you to record & replay HTTP responses. + +Install +------- + +.. code-block:: bash + + $ composer require --dev php-http/vcr-plugin + +Usage +----- + +To record or replay a response, you will need two components, a **naming strategy** and a **recorder**. + +The naming strategy +******************* + +The naming strategy turn a request into a deterministic and unique identifier. +The identifier must be safe to use with a filesystem. +The plugin provide a default naming strategy, the ``PathNamingStrategy``. You can define two options: + +* **hash_headers**: the list of header names to hash (Ex: Authorization), +* **hash_body_methods**: methods for which the body will be hashed (Default: PUT, POST, PATCH) + +This naming strategy will turn a GET request to https://example.org/my-path to the ``example.org_GET_my-path`` name, and optionally add hashes if the request +contain a header defined in the options, or if the method is not idempotent. + +To create your own strategy, you need to create a class implementing ``Http\Client\Plugin\Vcr\NamingStrategy\NamingStrategyInterface``. + +The recorder +************ + +The recorder records and replays responses. The plugin provide a two recorders: + +* ``FilesystemRecorder``: Saves the response on your filesystem using Symfony's `filesystem component`_ and `Guzzle PSR7`_ library. +* ``InMemoryRecorder``: Saves the response in memory. **Response will be lost at the end of the running process** + +To create your own recorder, you need to create a class implementing the following interfaces: + +* ``Http\Client\Plugin\Vcr\Recorder\RecorderInterface`` used by the RecordPlugin. +* ``Http\Client\Plugin\Vcr\Recorder\PlayerInterface`` used by the ReplayPlugin. + +The plugins +*********** + +VCR come built-in with two plugins: + +* ``Http\Client\Plugin\Vcr\ReplayPlugin``, use a ``PlayerInterface`` to replay previously recorded responses. +* ``Http\Client\Plugin\Vcr\RecordPlugin``, use a ``RecorderInterface`` instance to record the responses, + +If you plan on using both plugins at the same time (Replay or Record), the ``ReplayPlugin`` **must always** come first. +Please also note that by default, the ``ReplayPlugin`` throw an exception when it cannot replay a request, unless you set the third constructor argument to ``false`` (See example below). + +Example +******* + +.. code-block:: php + + ['X-Custom-Header'], // None by default + 'hash_body_methods' => ['POST'], // Default: PUT, POST, PATCH + ]); + $recorder = new FilesystemRecorder('some/dir/in/vcs'); // You can use InMemoryRecorder as well + + // To record responses: + $record = new RecordPlugin($namingStrategy, $recorder); + + // To replay responses: + // Third argument prevent the plugin from throwing an exception when a request cannot be replayed + $replay = new ReplayPlugin($namingStrategy, $recorder, false); + + $pluginClient = new PluginClient( + HttpClientDiscovery::find(), + [$replay, $record] // Replay should always go first + ); + + // Will be recorded in "some/dir/in/vcs" + $client->sendRequest(//...); + + // Will be replayed from "some/dir/in/vcs" + $client->sendRequest(//...); + +.. _filesystem component: https://symfony.com/doc/current/components/filesystem.html +.. _Guzzle PSR7: https://github.com/guzzle/psr7 \ No newline at end of file From 677034063dc15bebf7c36a3c0281b29edf43c9a8 Mon Sep 17 00:00:00 2001 From: Gary PEGEOT Date: Mon, 1 Apr 2019 22:00:11 +0100 Subject: [PATCH 2/3] Type fix, add additional info --- plugins/vcr.rst | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/plugins/vcr.rst b/plugins/vcr.rst index 9c19c66..0082aba 100644 --- a/plugins/vcr.rst +++ b/plugins/vcr.rst @@ -1,7 +1,10 @@ -VCR Plugin -========== +VCR Plugin - Record and Replay Responses +======================================== -The VCR plugins allow you to record & replay HTTP responses. +The VCR plugins allow you to record & replay HTTP responses. It's very useful for test purpose (using production-like predictable fixtures and avoid making actual HTTP request). +You can also use it during your development cycle, when the endpoint you're contacting is not ready yet. + +Unlike the :doc:`php-http/mock-client `, where you have to manually define responses, the responses are **automatically** generated from the previously recorded ones. Install ------- @@ -22,8 +25,8 @@ The naming strategy turn a request into a deterministic and unique identifier. The identifier must be safe to use with a filesystem. The plugin provide a default naming strategy, the ``PathNamingStrategy``. You can define two options: -* **hash_headers**: the list of header names to hash (Ex: Authorization), -* **hash_body_methods**: methods for which the body will be hashed (Default: PUT, POST, PATCH) +* **hash_headers**: the list of header(s) that make the request unique (Ex: 'Authorization'). The content of the header will be hashed to generate a unique signature. By default no header is used. +* **hash_body_methods**: indicate for which request methods the body makes requests distinct. (Default: PUT, POST, PATCH) This naming strategy will turn a GET request to https://example.org/my-path to the ``example.org_GET_my-path`` name, and optionally add hashes if the request contain a header defined in the options, or if the method is not idempotent. @@ -33,7 +36,7 @@ To create your own strategy, you need to create a class implementing ``Http\Clie The recorder ************ -The recorder records and replays responses. The plugin provide a two recorders: +The recorder records and replays responses. The plugin provides two recorders: * ``FilesystemRecorder``: Saves the response on your filesystem using Symfony's `filesystem component`_ and `Guzzle PSR7`_ library. * ``InMemoryRecorder``: Saves the response in memory. **Response will be lost at the end of the running process** @@ -46,13 +49,15 @@ To create your own recorder, you need to create a class implementing the followi The plugins *********** -VCR come built-in with two plugins: +There are two plugins, one to record responses, the other to replay them. * ``Http\Client\Plugin\Vcr\ReplayPlugin``, use a ``PlayerInterface`` to replay previously recorded responses. * ``Http\Client\Plugin\Vcr\RecordPlugin``, use a ``RecorderInterface`` instance to record the responses, +Both plugins add a response header to indicate either under which name the response has been stored (RecordPlugin, ``X-VCR-RECORD`` header), or which response name has been used to replay the request (ReplayPlugin, ``X-VCR-REPLAYED`` header). + If you plan on using both plugins at the same time (Replay or Record), the ``ReplayPlugin`` **must always** come first. -Please also note that by default, the ``ReplayPlugin`` throw an exception when it cannot replay a request, unless you set the third constructor argument to ``false`` (See example below). +Please also note that by default, the ``ReplayPlugin`` throws an exception when it cannot replay a request. If you want the plugin to continue the request (possibly to the actual server), set the third constructor argument to ``false`` (See example below). Example ******* @@ -86,11 +91,14 @@ Example [$replay, $record] // Replay should always go first ); + /** @var \Psr\Http\Message\RequestInterface $request */ + $request = new MyRequest('GET', 'https://httplug.io'); + // Will be recorded in "some/dir/in/vcs" - $client->sendRequest(//...); + $client->sendRequest($request); // Will be replayed from "some/dir/in/vcs" - $client->sendRequest(//...); + $client->sendRequest($request); .. _filesystem component: https://symfony.com/doc/current/components/filesystem.html -.. _Guzzle PSR7: https://github.com/guzzle/psr7 \ No newline at end of file +.. _Guzzle PSR7: https://github.com/guzzle/psr7 From fdfd25c43a67c0d094258bf1daf7847575597f66 Mon Sep 17 00:00:00 2001 From: Gary PEGEOT Date: Tue, 2 Apr 2019 09:28:05 +0100 Subject: [PATCH 3/3] Update wording --- plugins/vcr.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/vcr.rst b/plugins/vcr.rst index 0082aba..8b24070 100644 --- a/plugins/vcr.rst +++ b/plugins/vcr.rst @@ -25,7 +25,7 @@ The naming strategy turn a request into a deterministic and unique identifier. The identifier must be safe to use with a filesystem. The plugin provide a default naming strategy, the ``PathNamingStrategy``. You can define two options: -* **hash_headers**: the list of header(s) that make the request unique (Ex: 'Authorization'). The content of the header will be hashed to generate a unique signature. By default no header is used. +* **hash_headers**: the list of header(s) that make the request unique (Ex: 'Authorization'). The name & content of the header will be hashed to generate a unique signature. By default no header is used. * **hash_body_methods**: indicate for which request methods the body makes requests distinct. (Default: PUT, POST, PATCH) This naming strategy will turn a GET request to https://example.org/my-path to the ``example.org_GET_my-path`` name, and optionally add hashes if the request