| 
<?phpnamespace GuzzleHttp;
 
 use GuzzleHttp\Promise\PromiseInterface;
 use GuzzleHttp\Psr7;
 use Psr\Http\Message\RequestInterface;
 
 /**
 * Prepares requests that contain a body, adding the Content-Length,
 * Content-Type, and Expect headers.
 */
 class PrepareBodyMiddleware
 {
 /** @var callable  */
 private $nextHandler;
 
 /** @var array */
 private static $skipMethods = ['GET' => true, 'HEAD' => true];
 
 /**
 * @param callable $nextHandler Next handler to invoke.
 */
 public function __construct(callable $nextHandler)
 {
 $this->nextHandler = $nextHandler;
 }
 
 /**
 * @param RequestInterface $request
 * @param array            $options
 *
 * @return PromiseInterface
 */
 public function __invoke(RequestInterface $request, array $options)
 {
 $fn = $this->nextHandler;
 
 // Don't do anything if the request has no body.
 if (isset(self::$skipMethods[$request->getMethod()])
 || $request->getBody()->getSize() === 0
 ) {
 return $fn($request, $options);
 }
 
 $modify = [];
 
 // Add a default content-type if possible.
 if (!$request->hasHeader('Content-Type')) {
 if ($uri = $request->getBody()->getMetadata('uri')) {
 if ($type = Psr7\mimetype_from_filename($uri)) {
 $modify['set_headers']['Content-Type'] = $type;
 }
 }
 }
 
 // Add a default content-length or transfer-encoding header.
 if (!isset(self::$skipMethods[$request->getMethod()])
 && !$request->hasHeader('Content-Length')
 && !$request->hasHeader('Transfer-Encoding')
 ) {
 $size = $request->getBody()->getSize();
 if ($size !== null) {
 $modify['set_headers']['Content-Length'] = $size;
 } else {
 $modify['set_headers']['Transfer-Encoding'] = 'chunked';
 }
 }
 
 // Add the expect header if needed.
 $this->addExpectHeader($request, $options, $modify);
 
 return $fn(Psr7\modify_request($request, $modify), $options);
 }
 
 private function addExpectHeader(
 RequestInterface $request,
 array $options,
 array &$modify
 ) {
 // Determine if the Expect header should be used
 if ($request->hasHeader('Expect')) {
 return;
 }
 
 $expect = isset($options['expect']) ? $options['expect'] : null;
 
 // Return if disabled or if you're not using HTTP/1.1 or HTTP/2.0
 if ($expect === false || $request->getProtocolVersion() < 1.1) {
 return;
 }
 
 // The expect header is unconditionally enabled
 if ($expect === true) {
 $modify['set_headers']['Expect'] = '100-Continue';
 return;
 }
 
 // By default, send the expect header when the payload is > 1mb
 if ($expect === null) {
 $expect = 1048576;
 }
 
 // Always add if the body cannot be rewound, the size cannot be
 // determined, or the size is greater than the cutoff threshold
 $body = $request->getBody();
 $size = $body->getSize();
 
 if ($size === null || $size >= (int) $expect || !$body->isSeekable()) {
 $modify['set_headers']['Expect'] = '100-Continue';
 }
 }
 }
 
 |