Completed
Pull Request — master (#157)
by Alexander
01:52
created

TrustedHostsNetworkResolverTest::testTrusted()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 32
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

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

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)
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()
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
            private $content;
169
170
            public function __construct(string $content)
171
            {
172
                $this->content = $content;
173
            }
174
175
            public function process(
176
                ServerRequestInterface $request,
177
                RequestHandlerInterface $handler
178
            ): ResponseInterface {
179
                $response = (new Psr17Factory())->createResponse(403);
180
                $response->getBody()->write($this->content);
181
                return $response;
182
            }
183
        });
184
        $response = $middleware->process($request, $requestHandler);
185
        $this->assertInstanceOf(ResponseInterface::class, $response);
186
        $this->assertSame(403, $response->getStatusCode());
187
        $body = $response->getBody();
188
        $body->rewind();
189
        $this->assertSame($content, $body->getContents());
190
    }
191
}
192