aboutsummaryrefslogtreecommitdiffstats
path: root/public/system/storage/vendor/guzzlehttp/guzzle/src/Subscriber/Prepare.php
blob: b5ed4e26092def223a216f0c00a02aa0d97cd17e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
<?php
namespace GuzzleHttp\Subscriber;

use GuzzleHttp\Event\BeforeEvent;
use GuzzleHttp\Event\RequestEvents;
use GuzzleHttp\Event\SubscriberInterface;
use GuzzleHttp\Message\AppliesHeadersInterface;
use GuzzleHttp\Message\RequestInterface;
use GuzzleHttp\Mimetypes;
use GuzzleHttp\Stream\StreamInterface;

/**
 * Prepares requests with a body before sending
 *
 * **Request Options**
 *
 * - expect: Set to true to enable the "Expect: 100-Continue" header for a
 *   request that send a body. Set to false to disable "Expect: 100-Continue".
 *   Set to a number so that the size of the payload must be greater than the
 *   number in order to send the Expect header. Setting to a number will send
 *   the Expect header for all requests in which the size of the payload cannot
 *   be determined or where the body is not rewindable.
 */
class Prepare implements SubscriberInterface
{
    public function getEvents()
    {
        return ['before' => ['onBefore', RequestEvents::PREPARE_REQUEST]];
    }

    public function onBefore(BeforeEvent $event)
    {
        $request = $event->getRequest();

        // Set the appropriate Content-Type for a request if one is not set and
        // there are form fields
        if (!($body = $request->getBody())) {
            return;
        }

        $this->addContentLength($request, $body);

        if ($body instanceof AppliesHeadersInterface) {
            // Synchronize the body with the request headers
            $body->applyRequestHeaders($request);
        } elseif (!$request->hasHeader('Content-Type')) {
            $this->addContentType($request, $body);
        }

        $this->addExpectHeader($request, $body);
    }

    private function addContentType(
        RequestInterface $request,
        StreamInterface $body
    ) {
        if (!($uri = $body->getMetadata('uri'))) {
            return;
        }

        // Guess the content-type based on the stream's "uri" metadata value.
        // The file extension is used to determine the appropriate mime-type.
        if ($contentType = Mimetypes::getInstance()->fromFilename($uri)) {
            $request->setHeader('Content-Type', $contentType);
        }
    }

    private function addContentLength(
        RequestInterface $request,
        StreamInterface $body
    ) {
        // Set the Content-Length header if it can be determined, and never
        // send a Transfer-Encoding: chunked and Content-Length header in
        // the same request.
        if ($request->hasHeader('Content-Length')) {
            // Remove transfer-encoding if content-length is set.
            $request->removeHeader('Transfer-Encoding');
            return;
        }

        if ($request->hasHeader('Transfer-Encoding')) {
            return;
        }

        if (null !== ($size = $body->getSize())) {
            $request->setHeader('Content-Length', $size);
            $request->removeHeader('Transfer-Encoding');
        } elseif ('1.1' == $request->getProtocolVersion()) {
            // Use chunked Transfer-Encoding if there is no determinable
            // content-length header and we're using HTTP/1.1.
            $request->setHeader('Transfer-Encoding', 'chunked');
            $request->removeHeader('Content-Length');
        }
    }

    private function addExpectHeader(
        RequestInterface $request,
        StreamInterface $body
    ) {
        // Determine if the Expect header should be used
        if ($request->hasHeader('Expect')) {
            return;
        }

        $expect = $request->getConfig()['expect'];

        // Return if disabled or if you're not using HTTP/1.1
        if ($expect === false || $request->getProtocolVersion() !== '1.1') {
            return;
        }

        // The expect header is unconditionally enabled
        if ($expect === true) {
            $request->setHeader('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
        $size = $body->getSize();
        if ($size === null || $size >= (int) $expect || !$body->isSeekable()) {
            $request->setHeader('Expect', '100-Continue');
        }
    }
}