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