Ei kuvausta

PrepareBodyMiddleware.php 3.3KB

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