Completed
Pull Request — master (#157)
by
unknown
02:01
created

TrustedHostsNetworkResolverTest::testTrusted()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 32
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 5
Bugs 0 Features 0
Metric Value
cc 3
eloc 19
c 5
b 0
f 0
nc 4
nop 8
dl 0
loc 32
rs 9.6333

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
namespace Yiisoft\Yii\Web\Tests\Middleware;
4
5
use Nyholm\Psr7\Factory\Psr17Factory;
6
use Nyholm\Psr7\ServerRequest;
7
use PHPUnit\Framework\TestCase;
8
use Psr\Http\Message\ResponseInterface;
9
use Psr\Http\Message\ServerRequestInterface;
10
use Psr\Http\Server\MiddlewareInterface;
11
use Psr\Http\Server\RequestHandlerInterface;
12
use Yiisoft\Yii\Web\Middleware\TrustedHostsNetworkResolver;
13
use Yiisoft\Yii\Web\Tests\Middleware\Mock\MockRequestHandler;
14
15
class TrustedHostsNetworkResolverTest extends TestCase
16
{
17
    protected function newRequestWithSchemaAndHeaders(
18
        string $scheme = 'http',
19
        array $headers = [],
20
        array $serverParams = []
21
    ): ServerRequestInterface {
22
        $request = new ServerRequest('GET', '/', $headers, null, '1.1', $serverParams);
23
        $uri = $request->getUri()->withScheme($scheme);
24
        return $request->withUri($uri);
25
    }
26
27
    public function trustedDataProvider(): array
28
    {
29
        return [
30
            'xForwardLevel1' => [
31
                ['x-forwarded-for' => ['9.9.9.9', '5.5.5.5', '2.2.2.2']],
32
                ['REMOTE_ADDR' => '127.0.0.1'],
33
                [
34
                    ['hosts' => ['8.8.8.8', '127.0.0.1'], 'ipHeaders' => ['x-forwarded-for']]
35
                ],
36
                '2.2.2.2',
37
            ],
38
            'xForwardLevel2' => [
39
                ['x-forwarded-for' => ['9.9.9.9', '5.5.5.5', '2.2.2.2']],
40
                ['REMOTE_ADDR' => '127.0.0.1'],
41
                [
42
                    ['hosts' => ['8.8.8.8', '127.0.0.1', '2.2.2.2'], 'ipHeaders' => ['x-forwarded-for']],
43
                ],
44
                '5.5.5.5',
45
            ],
46
            'rfc7239Level1' => [
47
                ['forwarded' => ['for=9.9.9.9', 'for=5.5.5.5', 'for=2.2.2.2']],
48
                ['REMOTE_ADDR' => '127.0.0.1'],
49
                [
50
                    [
51
                        'hosts' => ['8.8.8.8', '127.0.0.1'],
52
                        'ipHeaders' => [[TrustedHostsNetworkResolver::IP_HEADER_TYPE_RFC7239, 'forwarded']],
53
                    ]
54
                ],
55
                '2.2.2.2',
56
            ],
57
            'rfc7239Level2' => [
58
                ['forwarded' => ['for=9.9.9.9', 'for=5.5.5.5', 'for=2.2.2.2']],
59
                ['REMOTE_ADDR' => '127.0.0.1'],
60
                [
61
                    [
62
                        'hosts' => ['8.8.8.8', '127.0.0.1', '2.2.2.2'],
63
                        'ipHeaders' => [[TrustedHostsNetworkResolver::IP_HEADER_TYPE_RFC7239, 'forwarded']],
64
                    ],
65
66
                ],
67
                '5.5.5.5',
68
            ],
69
            'rfc7239Level2HostAndProtocol' => [
70
                ['forwarded' => ['for=9.9.9.9', 'proto=https;for=5.5.5.5;host=test', 'for=2.2.2.2']],
71
                ['REMOTE_ADDR' => '127.0.0.1'],
72
                [
73
                    [
74
                        'hosts' => ['8.8.8.8', '127.0.0.1', '2.2.2.2'],
75
                        'ipHeaders' => [[TrustedHostsNetworkResolver::IP_HEADER_TYPE_RFC7239, 'forwarded']],
76
                        'hostHeaders' => ['forwarded'],
77
                        'protocolHeaders' => ['forwarded' => ['http' => 'http', 'https' => 'https']],
78
                    ],
79
                ],
80
                '5.5.5.5',
81
                'test',
82
                'https',
83
            ],
84
            'rfc7239Level2HostAndProtocolAndUrl' => [
85
                [
86
                    'forwarded' => ['for=9.9.9.9', 'proto=https;for=5.5.5.5;host=test', 'for=2.2.2.2'],
87
                    'x-rewrite-url' => ['/test?test=test'],
88
                ],
89
                ['REMOTE_ADDR' => '127.0.0.1'],
90
                [
91
                    [
92
                        'hosts' => ['8.8.8.8', '127.0.0.1', '2.2.2.2'],
93
                        'ipHeaders' => [[TrustedHostsNetworkResolver::IP_HEADER_TYPE_RFC7239, 'forwarded']],
94
                        'hostHeaders' => ['forwarded'],
95
                        'protocolHeaders' => ['forwarded' => ['http' => 'http', 'https' => 'https']],
96
                        'urlHeaders' => ['x-rewrite-url'],
97
                    ],
98
                ],
99
                '5.5.5.5',
100
                'test',
101
                'https',
102
                '/test',
103
                'test=test',
104
            ],
105
        ];
106
    }
107
108
    /**
109
     * @dataProvider trustedDataProvider
110
     */
111
    public function testTrusted(
112
        array $headers,
113
        array $serverParams,
114
        array $trustedHosts,
115
        string $expectedClientIp,
116
        ?string $expectedHttpHost = null,
117
        string $expectedHttpScheme = 'http',
118
        string $expectedPath = '/',
119
        string $expectedQuery = ''
120
    ): void {
121
        $request = $this->newRequestWithSchemaAndHeaders('http', $headers, $serverParams);
122
        $requestHandler = new MockRequestHandler();
123
124
        $middleware = new TrustedHostsNetworkResolver(new Psr17Factory());
125
        foreach ($trustedHosts as $data) {
126
            $middleware = $middleware->withAddedTrustedHosts(
127
                $data['hosts'],
128
                $data['ipHeaders'] ?? [],
129
                $data['protocolHeaders'] ?? [],
130
                $data['hostHeaders'] ?? [],
131
                $data['urlHeaders'] ?? [],
132
                $data['trustedHeaders'] ?? null);
133
        }
134
        $response = $middleware->process($request, $requestHandler);
135
        $this->assertSame(200, $response->getStatusCode());
136
        $this->assertSame($expectedClientIp, $requestHandler->processedRequest->getAttribute('requestClientIp'));
137
        if ($expectedHttpHost !== null) {
138
            $this->assertSame($expectedHttpHost, $requestHandler->processedRequest->getUri()->getHost());
139
        }
140
        $this->assertSame($expectedHttpScheme, $requestHandler->processedRequest->getUri()->getScheme());
141
        $this->assertSame($expectedPath, $requestHandler->processedRequest->getUri()->getPath());
142
        $this->assertSame($expectedQuery, $requestHandler->processedRequest->getUri()->getQuery());
143
    }
144
145
    public function notTrustedDataProvider(): array
146
    {
147
        return [
148
            'none' => [
149
                [],
150
                ['REMOTE_ADDR' => '127.0.0.1'],
151
                [],
152
            ],
153
            'x-forwarded-for' => [
154
                ['x-forwarded-for' => ['9.9.9.9', '5.5.5.5', '2.2.2.2']],
155
                ['REMOTE_ADDR' => '127.0.0.1'],
156
                [['hosts' => ['8.8.8.8'], 'ipHeaders' => ['x-forwarded-for']]],
157
            ],
158
            'rfc7239' => [
159
                ['x-forwarded-for' => ['for=9.9.9.9', 'for=5.5.5.5', 'for=2.2.2.2']],
160
                ['REMOTE_ADDR' => '127.0.0.1'],
161
                [['hosts' => ['8.8.8.8'], 'ipHeaders' => ['x-forwarded-for']]],
162
            ],
163
        ];
164
    }
165
166
    /**
167
     * @dataProvider notTrustedDataProvider
168
     */
169
    public function testNotTrusted(array $headers, array $serverParams, array $trustedHosts): void
170
    {
171
        $request = $this->newRequestWithSchemaAndHeaders('http', $headers, $serverParams);
172
        $requestHandler = new MockRequestHandler();
173
174
        $middleware = new TrustedHostsNetworkResolver(new Psr17Factory());
175
        foreach ($trustedHosts as $data) {
176
            $middleware = $middleware->withAddedTrustedHosts(
177
                $data['hosts'],
178
                $data['ipHeaders'] ?? [],
179
                $data['protocolHeaders'] ?? [],
180
                [],
181
                [],
182
                $data['trustedHeaders'] ?? []);
183
        }
184
        $response = $middleware->process($request, $requestHandler);
185
        $this->assertSame(412, $response->getStatusCode());
186
    }
187
188
    public function testNotTrustedMiddleware(): void
189
    {
190
        $request = $this->newRequestWithSchemaAndHeaders('http', [], [
191
            'REMOTE_ADDR' => '127.0.0.1',
192
        ]);
193
        $requestHandler = new MockRequestHandler();
194
195
        $middleware = new TrustedHostsNetworkResolver(new Psr17Factory());
196
        $content = 'Another branch.';
197
        $middleware = $middleware->withNotTrustedBranch(new class($content) implements MiddlewareInterface
198
        {
199
            private $content;
200
201
            public function __construct(string $content)
202
            {
203
                $this->content = $content;
204
            }
205
206
            public function process(
207
                ServerRequestInterface $request,
208
                RequestHandlerInterface $handler
209
            ): ResponseInterface {
210
                $response = (new Psr17Factory())->createResponse(403);
211
                $response->getBody()->write($this->content);
212
                return $response;
213
            }
214
        });
215
        $response = $middleware->process($request, $requestHandler);
216
        $this->assertInstanceOf(ResponseInterface::class, $response);
217
        $this->assertSame(403, $response->getStatusCode());
218
        $body = $response->getBody();
219
        $body->rewind();
220
        $this->assertSame($content, $body->getContents());
221
    }
222
223
    public function addedTrustedHostsInvalidParameterDataProvider(): array
224
    {
225
        return [
226
            'hostsEmpty' => ['hosts' => []],
227
            'hostsEmptyString' => ['hosts' => ['']],
228
            'hostsNumeric' => ['hosts' => [888]],
229
            'hostsSpaces' => ['hosts' => ['    ']],
230
            'hostsNotDomain' => ['host' => ['-apple']],
231
            'urlHeadersEmpty' => ['urlHeaders' => ['']],
232
            'urlHeadersNumeric' => ['urlHeaders' => [888]],
233
            'urlHeadersSpaces' => ['urlHeaders' => ['   ']],
234
            'trustedHeadersEmpty' => ['trustedHeaders' => ['']],
235
            'trustedHeadersNumeric' => ['trustedHeaders' => [888]],
236
            'trustedHeadersSpaces' => ['trustedHeaders' => ['   ']],
237
            'protocolHeadersNumeric' => ['protocolHeaders' => ['http' => 888]],
238
            'ipHeadersEmptyString' => ['ipHeaders' => [' ']],
239
            'ipHeadersNumeric' => ['ipHeaders' => [888]],
240
            'ipHeadersInvalidType' => ['ipHeaders' => [['---', 'aaa']]],
241
            'ipHeadersInvalidTypeValue' => [
242
                'ipHeaders' => [
243
                    [
244
                        TrustedHostsNetworkResolver::IP_HEADER_TYPE_RFC7239,
245
                        888
246
                    ]
247
                ]
248
            ],
249
        ];
250
    }
251
252
    /**
253
     * @dataProvider addedTrustedHostsInvalidParameterDataProvider
254
     */
255
    public function testAddedTrustedHostsInvalidParameter(array $data): void
256
    {
257
        $this->expectException(\InvalidArgumentException::class);
258
        (new TrustedHostsNetworkResolver(new Psr17Factory()))
259
            ->withAddedTrustedHosts($data['hosts'] ?? [],
260
                $data['ipHeaders'] ?? [],
261
                $data['protocolHeaders'] ?? [],
262
                $data['hostHeaders'] ?? [],
263
                $data['urlHeaders'] ?? [],
264
                $data['trustedHeaders'] ?? null
265
            );
266
    }
267
}
268