Passed
Push — master ( 35232d...8d0b59 )
by Melech
06:16 queued 02:04
created

GuzzleClient::setGuzzleHeaders()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 4
dl 0
loc 7
rs 10
c 0
b 0
f 0
cc 3
nc 3
nop 2
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Valkyrja Framework package.
7
 *
8
 * (c) Melech Mizrachi <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Valkyrja\Http\Client;
15
16
use GuzzleHttp\Client;
17
use GuzzleHttp\Cookie\CookieJar;
18
use GuzzleHttp\Cookie\SetCookie;
19
use GuzzleHttp\Exception\GuzzleException;
20
use Psr\Http\Message\ResponseInterface;
21
use Valkyrja\Http\Client\Contract\Client as Contract;
22
use Valkyrja\Http\Message\Enum\StatusCode;
23
use Valkyrja\Http\Message\Factory\Contract\ResponseFactory;
24
use Valkyrja\Http\Message\Request\Contract\JsonServerRequest;
25
use Valkyrja\Http\Message\Request\Contract\Request;
26
use Valkyrja\Http\Message\Request\Contract\ServerRequest;
27
use Valkyrja\Http\Message\Response\Contract\Response;
28
29
/**
30
 * Class GuzzleClient.
31
 *
32
 * @author Melech Mizrachi
33
 */
34
class GuzzleClient implements Contract
35
{
36
    public function __construct(
37
        protected Client $client,
38
        protected ResponseFactory $responseFactory,
39
    ) {
40
    }
41
42
    /**
43
     * @inheritDoc
44
     *
45
     * @throws GuzzleException
46
     */
47
    public function sendRequest(Request $request): Response
48
    {
49
        return $this->fromPsr7($this->getGuzzleResponse($request));
50
    }
51
52
    /**
53
     * Get a Guzzle response from a Valkyrja request.
54
     *
55
     * @param Request $request The request
56
     *
57
     * @throws GuzzleException
58
     *
59
     * @return ResponseInterface
60
     */
61
    protected function getGuzzleResponse(Request $request): ResponseInterface
62
    {
63
        /** @var array<string, mixed> $options */
64
        $options = [];
65
66
        $this->setGuzzleHeaders($request, $options);
67
        $this->setGuzzleBody($request, $options);
68
69
        if ($request instanceof ServerRequest) {
70
            $this->setGuzzleCookies($request, $options);
71
            $this->setGuzzleFormParams($request, $options);
72
        }
73
74
        return $this->client->request(
75
            $request->getMethod()->value,
76
            $request->getUri()->__toString(),
77
            $options
78
        );
79
    }
80
81
    /**
82
     * Set the Guzzle headers.
83
     *
84
     * @param Request               $request The request
85
     * @param array<string, mixed> &$options The options
86
     *
87
     * @return void
88
     */
89
    protected function setGuzzleHeaders(Request $request, array &$options): void
90
    {
91
        if ($headers = $request->getHeaders()) {
92
            $options['headers'] = [];
93
94
            foreach ($headers as $header => $value) {
95
                $options['headers'][$header] = $value;
96
            }
97
        }
98
    }
99
100
    /**
101
     * Set the Guzzle cookies.
102
     *
103
     * @param ServerRequest         $request The request
104
     * @param array<string, mixed> &$options The options
105
     *
106
     * @return void
107
     */
108
    protected function setGuzzleCookies(ServerRequest $request, array &$options): void
109
    {
110
        if ($cookies = $request->getCookieParams()) {
111
            $jar = new CookieJar();
112
113
            foreach ($cookies as $name => $value) {
114
                $guzzleCookie = new SetCookie();
115
116
                $guzzleCookie->setName($name);
117
                $guzzleCookie->setValue($value ?? '');
118
119
                $jar->setCookie($guzzleCookie);
120
            }
121
122
            $options['cookies'] = $jar;
123
        }
124
    }
125
126
    /**
127
     * Set the Guzzle form params.
128
     *
129
     * @param ServerRequest         $request The request
130
     * @param array<string, mixed> &$options The options
131
     *
132
     * @return void
133
     */
134
    protected function setGuzzleFormParams(ServerRequest $request, array &$options): void
135
    {
136
        if (
137
            ($body = $request->getParsedBody())
138
            && ! ($request instanceof JsonServerRequest && $request->getParsedJson())
139
        ) {
140
            $options['form_params'] = $body;
141
        }
142
    }
143
144
    /**
145
     * Set the Guzzle body.
146
     *
147
     * @param Request               $request The request
148
     * @param array<string, mixed> &$options The options
149
     *
150
     * @return void
151
     */
152
    protected function setGuzzleBody(Request $request, array &$options): void
153
    {
154
        $body = $request->getBody();
155
        $body->rewind();
156
157
        if ($contents = $body->getContents()) {
158
            $options['body'] = $contents;
159
        }
160
    }
161
162
    /**
163
     * Convert a Guzzle Response to Valkyrja Response.
164
     *
165
     * @param ResponseInterface $guzzleResponse The Guzzle Response
166
     *
167
     * @return Response
168
     *
169
     * @psalm-suppress MixedArgumentTypeCoercion
170
     */
171
    protected function fromPsr7(ResponseInterface $guzzleResponse): Response
172
    {
173
        return $this->responseFactory->createResponse(
174
            $guzzleResponse->getBody()->getContents(),
175
            StatusCode::from($guzzleResponse->getStatusCode()),
176
            $guzzleResponse->getHeaders()
177
        );
178
    }
179
}
180