PrepareBodyMiddleware.php 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. <?php
  2. namespace GuzzleHttp;
  3. use GuzzleHttp\Promise\PromiseInterface;
  4. use GuzzleHttp\Psr7;
  5. use Psr\Http\Message\RequestInterface;
  6. /**
  7. * Prepares requests that contain a body, adding the Content-Length,
  8. * Content-Type, and Expect headers.
  9. */
  10. class PrepareBodyMiddleware
  11. {
  12. /** @var callable */
  13. private $nextHandler;
  14. /**
  15. * @param callable $nextHandler Next handler to invoke.
  16. */
  17. public function __construct(callable $nextHandler)
  18. {
  19. $this->nextHandler = $nextHandler;
  20. }
  21. /**
  22. * @param RequestInterface $request
  23. * @param array $options
  24. *
  25. * @return PromiseInterface
  26. */
  27. public function __invoke(RequestInterface $request, array $options)
  28. {
  29. $fn = $this->nextHandler;
  30. // Don't do anything if the request has no body.
  31. if ($request->getBody()->getSize() === 0) {
  32. return $fn($request, $options);
  33. }
  34. $modify = [];
  35. // Add a default content-type if possible.
  36. if (!$request->hasHeader('Content-Type')) {
  37. if ($uri = $request->getBody()->getMetadata('uri')) {
  38. if ($type = Psr7\mimetype_from_filename($uri)) {
  39. $modify['set_headers']['Content-Type'] = $type;
  40. }
  41. }
  42. }
  43. // Add a default content-length or transfer-encoding header.
  44. if (!$request->hasHeader('Content-Length')
  45. && !$request->hasHeader('Transfer-Encoding')
  46. ) {
  47. $size = $request->getBody()->getSize();
  48. if ($size !== null) {
  49. $modify['set_headers']['Content-Length'] = $size;
  50. } else {
  51. $modify['set_headers']['Transfer-Encoding'] = 'chunked';
  52. }
  53. }
  54. // Add the expect header if needed.
  55. $this->addExpectHeader($request, $options, $modify);
  56. return $fn(Psr7\modify_request($request, $modify), $options);
  57. }
  58. private function addExpectHeader(
  59. RequestInterface $request,
  60. array $options,
  61. array &$modify
  62. ) {
  63. // Determine if the Expect header should be used
  64. if ($request->hasHeader('Expect')) {
  65. return;
  66. }
  67. $expect = isset($options['expect']) ? $options['expect'] : null;
  68. // Return if disabled or if you're not using HTTP/1.1 or HTTP/2.0
  69. if ($expect === false || $request->getProtocolVersion() < 1.1) {
  70. return;
  71. }
  72. // The expect header is unconditionally enabled
  73. if ($expect === true) {
  74. $modify['set_headers']['Expect'] = '100-Continue';
  75. return;
  76. }
  77. // By default, send the expect header when the payload is > 1mb
  78. if ($expect === null) {
  79. $expect = 1048576;
  80. }
  81. // Always add if the body cannot be rewound, the size cannot be
  82. // determined, or the size is greater than the cutoff threshold
  83. $body = $request->getBody();
  84. $size = $body->getSize();
  85. if ($size === null || $size >= (int) $expect || !$body->isSeekable()) {
  86. $modify['set_headers']['Expect'] = '100-Continue';
  87. }
  88. }
  89. }