Completed
Pull Request — master (#157)
by
unknown
02:02
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
            'rfc7239Level2AnotherHostAndAnotherProtocolAndUrl' => [
106
                [
107
                    'forwarded' => ['for=9.9.9.9', 'proto=https;for=5.5.5.5;host=test', 'for=2.2.2.2'],
108
                    'x-rewrite-url' => ['/test?test=test'],
109
                    'x-forwarded-host' => ['test.another'],
110
                    'x-forwarded-proto' => ['on']
111
                ],
112
                ['REMOTE_ADDR' => '127.0.0.1'],
113
                [
114
                    [
115
                        'hosts' => ['8.8.8.8', '127.0.0.1', '2.2.2.2'],
116
                        'ipHeaders' => [[TrustedHostsNetworkResolver::IP_HEADER_TYPE_RFC7239, 'forwarded']],
117
                        'hostHeaders' => ['x-forwarded-host', 'forwarded'],
118
                        'protocolHeaders' => [
119
                            'x-forwarded-proto' => ['http' => 'http', 'httpsss' => 'on'],
120
                            'forwarded' => ['http' => 'http', 'https' => 'https']
121
                        ],
122
                        'urlHeaders' => ['x-rewrite-url'],
123
                    ],
124
                ],
125
                '5.5.5.5',
126
                'test.another',
127
                'httpsss',
128
                '/test',
129
                'test=test',
130
            ],
131
        ];
132
    }
133
134
    /**
135
     * @dataProvider trustedDataProvider
136
     */
137
    public function testTrusted(
138
        array $headers,
139
        array $serverParams,
140
        array $trustedHosts,
141
        string $expectedClientIp,
142
        ?string $expectedHttpHost = null,
143
        string $expectedHttpScheme = 'http',
144
        string $expectedPath = '/',
145
        string $expectedQuery = ''
146
    ): void {
147
        $request = $this->newRequestWithSchemaAndHeaders('http', $headers, $serverParams);
148
        $requestHandler = new MockRequestHandler();
149
150
        $middleware = new TrustedHostsNetworkResolver(new Psr17Factory());
151
        foreach ($trustedHosts as $data) {
152
            $middleware = $middleware->withAddedTrustedHosts(
153
                $data['hosts'],
154
                $data['ipHeaders'] ?? [],
155
                $data['protocolHeaders'] ?? [],
156
                $data['hostHeaders'] ?? [],
157
                $data['urlHeaders'] ?? [],
158
                $data['trustedHeaders'] ?? null);
159
        }
160
        $response = $middleware->process($request, $requestHandler);
161
        $this->assertSame(200, $response->getStatusCode());
162
        $this->assertSame($expectedClientIp, $requestHandler->processedRequest->getAttribute('requestClientIp'));
163
        if ($expectedHttpHost !== null) {
164
            $this->assertSame($expectedHttpHost, $requestHandler->processedRequest->getUri()->getHost());
165
        }
166
        $this->assertSame($expectedHttpScheme, $requestHandler->processedRequest->getUri()->getScheme());
167
        $this->assertSame($expectedPath, $requestHandler->processedRequest->getUri()->getPath());
168
        $this->assertSame($expectedQuery, $requestHandler->processedRequest->getUri()->getQuery());
169
    }
170
171
    public function notTrustedDataProvider(): array
172
    {
173
        return [
174
            'none' => [
175
                [],
176
                ['REMOTE_ADDR' => '127.0.0.1'],
177
                [],
178
            ],
179
            'x-forwarded-for' => [
180
                ['x-forwarded-for' => ['9.9.9.9', '5.5.5.5', '2.2.2.2']],
181
                ['REMOTE_ADDR' => '127.0.0.1'],
182
                [['hosts' => ['8.8.8.8'], 'ipHeaders' => ['x-forwarded-for']]],
183
            ],
184
            'rfc7239' => [
185
                ['x-forwarded-for' => ['for=9.9.9.9', 'for=5.5.5.5', 'for=2.2.2.2']],
186
                ['REMOTE_ADDR' => '127.0.0.1'],
187
                [['hosts' => ['8.8.8.8'], 'ipHeaders' => ['x-forwarded-for']]],
188
            ],
189
        ];
190
    }
191
192
    /**
193
     * @dataProvider notTrustedDataProvider
194
     */
195
    public function testNotTrusted(array $headers, array $serverParams, array $trustedHosts): void
196
    {
197
        $request = $this->newRequestWithSchemaAndHeaders('http', $headers, $serverParams);
198
        $requestHandler = new MockRequestHandler();
199
200
        $middleware = new TrustedHostsNetworkResolver(new Psr17Factory());
201
        foreach ($trustedHosts as $data) {
202
            $middleware = $middleware->withAddedTrustedHosts(
203
                $data['hosts'],
204
                $data['ipHeaders'] ?? [],
205
                $data['protocolHeaders'] ?? [],
206
                [],
207
                [],
208
                $data['trustedHeaders'] ?? []);
209
        }
210
        $response = $middleware->process($request, $requestHandler);
211
        $this->assertSame(412, $response->getStatusCode());
212
    }
213
214
    public function testNotTrustedMiddleware(): void
215
    {
216
        $request = $this->newRequestWithSchemaAndHeaders('http', [], [
217
            'REMOTE_ADDR' => '127.0.0.1',
218
        ]);
219
        $requestHandler = new MockRequestHandler();
220
221
        $middleware = new TrustedHostsNetworkResolver(new Psr17Factory());
222
        $content = 'Another branch.';
223
        $middleware = $middleware->withNotTrustedBranch(new class($content) implements MiddlewareInterface {
224
            private $content;
225
226
            public function __construct(string $content)
227
            {
228
                $this->content = $content;
229
            }
230
231
            public function process(
232
                ServerRequestInterface $request,
233
                RequestHandlerInterface $handler
234
            ): ResponseInterface {
235
                $response = (new Psr17Factory())->createResponse(403);
236
                $response->getBody()->write($this->content);
237
                return $response;
238
            }
239
        });
240
        $response = $middleware->process($request, $requestHandler);
241
        $this->assertInstanceOf(ResponseInterface::class, $response);
242
        $this->assertSame(403, $response->getStatusCode());
243
        $body = $response->getBody();
244
        $body->rewind();
245
        $this->assertSame($content, $body->getContents());
246
    }
247
248
    public function addedTrustedHostsInvalidParameterDataProvider(): array
249
    {
250
        return [
251
            'hostsEmpty' => ['hosts' => []],
252
            'hostsEmptyString' => ['hosts' => ['']],
253
            'hostsNumeric' => ['hosts' => [888]],
254
            'hostsSpaces' => ['hosts' => ['    ']],
255
            'hostsNotDomain' => ['host' => ['-apple']],
256
            'urlHeadersEmpty' => ['urlHeaders' => ['']],
257
            'urlHeadersNumeric' => ['urlHeaders' => [888]],
258
            'urlHeadersSpaces' => ['urlHeaders' => ['   ']],
259
            'trustedHeadersEmpty' => ['trustedHeaders' => ['']],
260
            'trustedHeadersNumeric' => ['trustedHeaders' => [888]],
261
            'trustedHeadersSpaces' => ['trustedHeaders' => ['   ']],
262
            'protocolHeadersNumeric' => ['protocolHeaders' => ['http' => 888]],
263
            'ipHeadersEmptyString' => ['ipHeaders' => [' ']],
264
            'ipHeadersNumeric' => ['ipHeaders' => [888]],
265
            'ipHeadersInvalidType' => ['ipHeaders' => [['---', 'aaa']]],
266
            'ipHeadersInvalidTypeValue' => [
267
                'ipHeaders' => [
268
                    [
269
                        TrustedHostsNetworkResolver::IP_HEADER_TYPE_RFC7239,
270
                        888
271
                    ]
272
                ]
273
            ],
274
        ];
275
    }
276
277
    /**
278
     * @dataProvider addedTrustedHostsInvalidParameterDataProvider
279
     */
280
    public function testAddedTrustedHostsInvalidParameter(array $data): void
281
    {
282
        $this->expectException(\InvalidArgumentException::class);
283
        (new TrustedHostsNetworkResolver(new Psr17Factory()))
284
            ->withAddedTrustedHosts($data['hosts'] ?? [],
285
                $data['ipHeaders'] ?? [],
286
                $data['protocolHeaders'] ?? [],
287
                $data['hostHeaders'] ?? [],
288
                $data['urlHeaders'] ?? [],
289
                $data['trustedHeaders'] ?? null
290
            );
291
    }
292
}
293