krz/vox-populi

A Tumblr web client.

clone: git clone https://gitbay.org/krz/vox-populi.git

main: vendor/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php · raw

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