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

TrustedHostsNetworkResolverTest::testTrusted()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 32
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
cc 3
eloc 19
c 4
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
                [['hosts' => ['8.8.8.8', '127.0.0.1']]],
34
                '2.2.2.2',
35
            ],
36
            'xForwardLevel2' => [
37
                ['x-forwarded-for' => ['9.9.9.9', '5.5.5.5', '2.2.2.2']],
38
                ['REMOTE_ADDR' => '127.0.0.1'],
39
                [['hosts' => ['8.8.8.8', '127.0.0.1', '2.2.2.2']]],
40
                '5.5.5.5',
41
            ],
42
            'forwardLevel1' => [
43
                ['forward' => ['for=9.9.9.9', 'for=5.5.5.5', 'for=2.2.2.2']],
44
                ['REMOTE_ADDR' => '127.0.0.1'],
45
                [['hosts' => ['8.8.8.8', '127.0.0.1']]],
46
                '2.2.2.2',
47
            ],
48
            'forwardLevel2' => [
49
                ['forward' => ['for=9.9.9.9', 'for=5.5.5.5', 'for=2.2.2.2']],
50
                ['REMOTE_ADDR' => '127.0.0.1'],
51
                [['hosts' => ['8.8.8.8', '127.0.0.1', '2.2.2.2']]],
52
                '5.5.5.5',
53
            ],
54
            'forwardLevel2HostAndProtocol' => [
55
                ['forward' => ['for=9.9.9.9', 'proto=https;for=5.5.5.5;host=test', 'for=2.2.2.2']],
56
                ['REMOTE_ADDR' => '127.0.0.1'],
57
                [['hosts' => ['8.8.8.8', '127.0.0.1', '2.2.2.2']]],
58
                '5.5.5.5',
59
                'test',
60
                'https',
61
            ],
62
            'forwardLevel2HostAndProtocolAndUrl' => [
63
                [
64
                    'forward' => ['for=9.9.9.9', 'proto=https;for=5.5.5.5;host=test', 'for=2.2.2.2'],
65
                    'x-rewrite-url' => ['/test?test=test'],
66
                ],
67
                ['REMOTE_ADDR' => '127.0.0.1'],
68
                [['hosts' => ['8.8.8.8', '127.0.0.1', '2.2.2.2']]],
69
                '5.5.5.5',
70
                'test',
71
                'https',
72
                '/test',
73
                'test=test',
74
            ],
75
        ];
76
    }
77
78
    /**
79
     * @dataProvider trustedDataProvider
80
     */
81
    public function testTrusted(
82
        array $headers,
83
        array $serverParams,
84
        array $trustedHosts,
85
        string $expectedClientIp,
86
        ?string $expectedHttpHost = null,
87
        string $expectedHttpScheme = 'http',
88
        string $expectedPath = '/',
89
        string $expectedQuery = ''
90
    ): void {
91
        $request = $this->newRequestWithSchemaAndHeaders('http', $headers, $serverParams);
92
        $requestHandler = new MockRequestHandler();
93
94
        $middleware = new TrustedHostsNetworkResolver(new Psr17Factory());
95
        foreach ($trustedHosts as $data) {
96
            $middleware = $middleware->withAddedTrustedHosts(
97
                $data['hosts'],
98
                $data['ipHeaders'] ?? null,
99
                $data['protocolHeaders'] ?? null,
100
                null,
101
                null,
102
                $data['trustedHeaders'] ?? null);
103
        }
104
        $response = $middleware->process($request, $requestHandler);
105
        $this->assertSame(200, $response->getStatusCode());
106
        $this->assertSame($expectedClientIp, $requestHandler->processedRequest->getAttribute('requestClientIp'));
107
        if ($expectedHttpHost !== null) {
108
            $this->assertSame($expectedHttpHost, $requestHandler->processedRequest->getUri()->getHost());
109
        }
110
        $this->assertSame($expectedHttpScheme, $requestHandler->processedRequest->getUri()->getScheme());
111
        $this->assertSame($expectedPath, $requestHandler->processedRequest->getUri()->getPath());
112
        $this->assertSame($expectedQuery, $requestHandler->processedRequest->getUri()->getQuery());
113
    }
114
115
    public function notTrustedDataProvider(): array
116
    {
117
        return [
118
            'none' => [
119
                [],
120
                ['REMOTE_ADDR' => '127.0.0.1'],
121
                [],
122
            ],
123
            'x-forwarded-for' => [
124
                ['x-forwarded-for' => ['9.9.9.9', '5.5.5.5', '2.2.2.2']],
125
                ['REMOTE_ADDR' => '127.0.0.1'],
126
                [['hosts' => ['8.8.8.8']]],
127
            ],
128
            'forward' => [
129
                ['x-forwarded-for' => ['for=9.9.9.9', 'for=5.5.5.5', 'for=2.2.2.2']],
130
                ['REMOTE_ADDR' => '127.0.0.1'],
131
                [['hosts' => ['8.8.8.8']]],
132
            ],
133
        ];
134
    }
135
136
    /**
137
     * @dataProvider notTrustedDataProvider
138
     */
139
    public function testNotTrusted(array $headers, array $serverParams, array $trustedHosts): void
140
    {
141
        $request = $this->newRequestWithSchemaAndHeaders('http', $headers, $serverParams);
142
        $requestHandler = new MockRequestHandler();
143
144
        $middleware = new TrustedHostsNetworkResolver(new Psr17Factory());
145
        foreach ($trustedHosts as $data) {
146
            $middleware = $middleware->withAddedTrustedHosts(
147
                $data['hosts'],
148
                $data['ipHeaders'] ?? null,
149
                $data['protocolHeaders'] ?? null,
150
                null,
151
                null,
152
                $data['trustedHeaders'] ?? null);
153
        }
154
        $response = $middleware->process($request, $requestHandler);
155
        $this->assertSame(412, $response->getStatusCode());
156
    }
157
158
    public function testNotTrustedMiddleware(): void
159
    {
160
        $request = $this->newRequestWithSchemaAndHeaders('http', [], [
161
            'REMOTE_ADDR' => '127.0.0.1',
162
        ]);
163
        $requestHandler = new MockRequestHandler();
164
165
        $middleware = new TrustedHostsNetworkResolver(new Psr17Factory());
166
        $content = 'Another branch.';
167
        $middleware = $middleware->withNotTrustedBranch(new class($content) implements MiddlewareInterface
168
        {
169
            private $content;
170
171
            public function __construct(string $content)
172
            {
173
                $this->content = $content;
174
            }
175
176
            public function process(
177
                ServerRequestInterface $request,
178
                RequestHandlerInterface $handler
179
            ): ResponseInterface {
180
                $response = (new Psr17Factory())->createResponse(403);
181
                $response->getBody()->write($this->content);
182
                return $response;
183
            }
184
        });
185
        $response = $middleware->process($request, $requestHandler);
186
        $this->assertInstanceOf(ResponseInterface::class, $response);
187
        $this->assertSame(403, $response->getStatusCode());
188
        $body = $response->getBody();
189
        $body->rewind();
190
        $this->assertSame($content, $body->getContents());
191
    }
192
193
    public function addedTrustedHostsInvalidParameterDataProvider(): array
194
    {
195
        return [
196
            'hostsEmpty' => ['hosts' => []],
197
            'hostsEmptyString' => ['hosts' => ['']],
198
            'hostsNumeric' => ['hosts' => [888]],
199
            'hostsSpaces' => ['hosts' => ['    ']],
200
            'hostsNotDomain' => ['host' => ['-apple']],
201
            'urlHeadersEmpty' => ['urlHeaders' => ['']],
202
            'urlHeadersNumeric' => ['urlHeaders' => [888]],
203
            'urlHeadersSpaces' => ['urlHeaders' => ['   ']],
204
            'trustedHeadersEmpty' => ['trustedHeaders' => ['']],
205
            'trustedHeadersNumeric' => ['trustedHeaders' => [888]],
206
            'trustedHeadersSpaces' => ['trustedHeaders' => ['   ']],
207
            'protocolHeadersNumeric' => ['protocolHeaders' => ['http' => 888]],
208
            'ipHeadersEmptyString' => ['ipHeaders' => [' ']],
209
            'ipHeadersNumeric' => ['ipHeaders' => [888]],
210
            'ipHeadersInvalidType' => ['ipHeaders' => [['---', 'aaa']]],
211
            'ipHeadersInvalidTypeValue' => [
212
                'ipHeaders' => [
213
                    [
214
                        TrustedHostsNetworkResolver::IP_HEADER_TYPE_RFC7239,
215
                        888
216
                    ]
217
                ]
218
            ],
219
        ];
220
    }
221
222
    /**
223
     * @dataProvider addedTrustedHostsInvalidParameterDataProvider
224
     */
225
    public function testAddedTrustedHostsInvalidParameter(array $data): void
226
    {
227
        $this->expectException(\InvalidArgumentException::class);
228
        (new TrustedHostsNetworkResolver(new Psr17Factory()))
229
            ->withAddedTrustedHosts($data['hosts'] ?? [],
230
                $data['ipHeaders'] ?? null,
231
                $data['protocolHeaders'] ?? null,
232
                $data['hostHeaders'] ?? null,
233
                $data['urlHeaders'] ?? null,
234
                $data['trustedHeaders'] ?? null
235
            );
236
    }
237
}
238