Subversion Repositories cheapmusic

Rev

Details | Last modification | View Log | RSS feed

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