Passed
Pull Request — master (#257)
by Wilmer
25:21 queued 10:17
created

TrustedHostsNetworkResolverTest::testTrusted()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 36
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 21
c 1
b 0
f 0
nc 4
nop 9
dl 0
loc 36
rs 9.584

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