client_middleware.rst 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. =================
  2. Client Middleware
  3. =================
  4. Middleware intercepts requests before they are sent over the wire and can be
  5. used to add functionality to handlers.
  6. Modifying Requests
  7. ------------------
  8. Let's say you wanted to modify requests before they are sent over the wire
  9. so that they always add specific headers. This can be accomplished by creating
  10. a function that accepts a handler and returns a new function that adds the
  11. composed behavior.
  12. .. code-block:: php
  13. use GuzzleHttp\Ring\Client\CurlHandler;
  14. $handler = new CurlHandler();
  15. $addHeaderHandler = function (callable $handler, array $headers = []) {
  16. return function (array $request) use ($handler, $headers) {
  17. // Add our custom headers
  18. foreach ($headers as $key => $value) {
  19. $request['headers'][$key] = $value;
  20. }
  21. // Send the request using the handler and return the response.
  22. return $handler($request);
  23. }
  24. };
  25. // Create a new handler that adds headers to each request.
  26. $handler = $addHeaderHandler($handler, [
  27. 'X-AddMe' => 'hello',
  28. 'Authorization' => 'Basic xyz'
  29. ]);
  30. $response = $handler([
  31. 'http_method' => 'GET',
  32. 'headers' => ['Host' => ['httpbin.org']]
  33. ]);
  34. Modifying Responses
  35. -------------------
  36. You can change a response as it's returned from a middleware. Remember that
  37. responses returned from an handler (including middleware) must implement
  38. ``GuzzleHttp\Ring\Future\FutureArrayInterface``. In order to be a good citizen,
  39. you should not expect that the responses returned through your middleware will
  40. be completed synchronously. Instead, you should use the
  41. ``GuzzleHttp\Ring\Core::proxy()`` function to modify the response when the
  42. underlying promise is resolved. This function is a helper function that makes it
  43. easy to create a new instance of ``FutureArrayInterface`` that wraps an existing
  44. ``FutureArrayInterface`` object.
  45. Let's say you wanted to add headers to a response as they are returned from
  46. your middleware, but you want to make sure you aren't causing future
  47. responses to be dereferenced right away. You can achieve this by modifying the
  48. incoming request and using the ``Core::proxy`` function.
  49. .. code-block:: php
  50. use GuzzleHttp\Ring\Core;
  51. use GuzzleHttp\Ring\Client\CurlHandler;
  52. $handler = new CurlHandler();
  53. $responseHeaderHandler = function (callable $handler, array $headers) {
  54. return function (array $request) use ($handler, $headers) {
  55. // Send the request using the wrapped handler.
  56. return Core::proxy($handler($request), function ($response) use ($headers) {
  57. // Add the headers to the response when it is available.
  58. foreach ($headers as $key => $value) {
  59. $response['headers'][$key] = (array) $value;
  60. }
  61. // Note that you can return a regular response array when using
  62. // the proxy method.
  63. return $response;
  64. });
  65. }
  66. };
  67. // Create a new handler that adds headers to each response.
  68. $handler = $responseHeaderHandler($handler, ['X-Header' => 'hello!']);
  69. $response = $handler([
  70. 'http_method' => 'GET',
  71. 'headers' => ['Host' => ['httpbin.org']]
  72. ]);
  73. assert($response['headers']['X-Header'] == 'hello!');
  74. Built-In Middleware
  75. -------------------
  76. RingPHP comes with a few basic client middlewares that modify requests
  77. and responses.
  78. Streaming Middleware
  79. ~~~~~~~~~~~~~~~~~~~~
  80. If you want to send all requests with the ``streaming`` option to a specific
  81. handler but other requests to a different handler, then use the streaming
  82. middleware.
  83. .. code-block:: php
  84. use GuzzleHttp\Ring\Client\CurlHandler;
  85. use GuzzleHttp\Ring\Client\StreamHandler;
  86. use GuzzleHttp\Ring\Client\Middleware;
  87. $defaultHandler = new CurlHandler();
  88. $streamingHandler = new StreamHandler();
  89. $streamingHandler = Middleware::wrapStreaming(
  90. $defaultHandler,
  91. $streamingHandler
  92. );
  93. // Send the request using the streaming handler.
  94. $response = $streamingHandler([
  95. 'http_method' => 'GET',
  96. 'headers' => ['Host' => ['www.google.com']],
  97. 'stream' => true
  98. ]);
  99. // Send the request using the default handler.
  100. $response = $streamingHandler([
  101. 'http_method' => 'GET',
  102. 'headers' => ['Host' => ['www.google.com']]
  103. ]);
  104. Future Middleware
  105. ~~~~~~~~~~~~~~~~~
  106. If you want to send all requests with the ``future`` option to a specific
  107. handler but other requests to a different handler, then use the future
  108. middleware.
  109. .. code-block:: php
  110. use GuzzleHttp\Ring\Client\CurlHandler;
  111. use GuzzleHttp\Ring\Client\CurlMultiHandler;
  112. use GuzzleHttp\Ring\Client\Middleware;
  113. $defaultHandler = new CurlHandler();
  114. $futureHandler = new CurlMultiHandler();
  115. $futureHandler = Middleware::wrapFuture(
  116. $defaultHandler,
  117. $futureHandler
  118. );
  119. // Send the request using the blocking CurlHandler.
  120. $response = $futureHandler([
  121. 'http_method' => 'GET',
  122. 'headers' => ['Host' => ['www.google.com']]
  123. ]);
  124. // Send the request using the non-blocking CurlMultiHandler.
  125. $response = $futureHandler([
  126. 'http_method' => 'GET',
  127. 'headers' => ['Host' => ['www.google.com']],
  128. 'future' => true
  129. ]);