Passed
Push — 4.6 ( fae61c...fbe0f5 )
by Garion
18:28 queued 10:28
created

HTTPRequestTest   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 377
Duplicated Lines 0 %

Importance

Changes 5
Bugs 0 Features 0
Metric Value
eloc 214
c 5
b 0
f 0
dl 0
loc 377
rs 10
wmc 16

15 Methods

Rating   Name   Duplication   Size   Complexity  
A testMatch() 0 11 1
A testWildCardMatch() 0 19 1
A testWildCardWithFurtherParams() 0 5 1
A setHttpMethodDataProvider() 0 9 1
A testGetURL() 0 11 1
A testIsAjax() 0 11 1
A detectMethodDataProvider() 0 16 1
A testDetectMethod() 0 4 1
A testHasSession() 0 7 1
A testSetHttpMethod() 0 6 1
B testRequestVars() 0 130 1
A testBadSetHttpMethod() 0 4 1
A testSetIPFromHeaderValue() 0 16 2
A testBadDetectMethod() 0 3 1
A testHttpMethodOverrides() 0 67 1
1
<?php
2
3
namespace SilverStripe\Control\Tests;
4
5
use ReflectionMethod;
6
use SilverStripe\Control\HTTPRequest;
7
use SilverStripe\Control\Middleware\TrustedProxyMiddleware;
8
use SilverStripe\Control\Session;
9
use SilverStripe\Dev\SapphireTest;
10
11
class HTTPRequestTest extends SapphireTest
12
{
13
    protected static $fixture_file = null;
14
15
    public function testMatch()
16
    {
17
        $request = new HTTPRequest("GET", "admin/crm/add");
18
19
        /* When a rule matches, but has no variables, array("_matched" => true) is returned. */
20
        $this->assertEquals(["_matched" => true], $request->match('admin/crm', true));
21
22
        /* Becasue we shifted admin/crm off the stack, just "add" should be remaining */
23
        $this->assertEquals("add", $request->remaining());
24
25
        $this->assertEquals(["_matched" => true], $request->match('add', true));
26
    }
27
28
    /**
29
     * @useDatabase false
30
     */
31
    public function testWildCardMatch()
32
    {
33
        $request = new HTTPRequest('GET', 'admin/crm/test');
34
        $this->assertEquals(['$1' => 'crm', '$2' => 'test'], $request->match('admin/$@', true));
35
        $this->assertTrue($request->allParsed());
36
37
        $request = new HTTPRequest('GET', 'admin/crm/test');
38
        $this->assertEquals(['_matched' => true], $request->match('admin/$*', true));
39
        $this->assertTrue($request->allParsed());
40
        $this->assertEquals('crm/test', $request->remaining());
41
42
        $request = new HTTPRequest('GET', 'admin/crm/test/part1/part2');
43
        $this->assertEquals(['Action' => 'crm', '$1' => 'test', '$2' => 'part1', '$3' => 'part2'], $request->match('admin/$Action/$@', true));
44
        $this->assertTrue($request->allParsed());
45
46
        $request = new HTTPRequest('GET', 'admin/crm/test/part1/part2');
47
        $this->assertEquals(['Action' => 'crm'], $request->match('admin/$Action/$*', true));
48
        $this->assertTrue($request->allParsed());
49
        $this->assertEquals('test/part1/part2', $request->remaining());
50
    }
51
52
    /**
53
     * This test just asserts a warning is given if there is more than one wildcard parameter. Note that this isn't an
54
     * enforcement of an API and we an add new behaviour in the future to allow many wildcard params if we want to
55
     *
56
     * @expectedException \PHPUnit_Framework_Error_Warning
57
     */
58
    public function testWildCardWithFurtherParams()
59
    {
60
        $request = new HTTPRequest('GET', 'admin/crm/test');
61
        // all parameters after the first wildcard parameter are ignored
62
        $request->match('admin/$Action/$@/$Other/$*', true);
63
    }
64
65
    public function testHttpMethodOverrides()
66
    {
67
        $request = new HTTPRequest(
68
            'GET',
69
            'admin/crm'
70
        );
71
        $this->assertTrue(
72
            $request->isGET(),
73
            'GET with no method override'
74
        );
75
76
        $request = new HTTPRequest(
77
            'POST',
78
            'admin/crm'
79
        );
80
        $this->assertTrue(
81
            $request->isPOST(),
82
            'POST with no method override'
83
        );
84
85
        $request = new HTTPRequest(
86
            'GET',
87
            'admin/crm',
88
            ['_method' => 'DELETE']
89
        );
90
        $this->assertTrue(
91
            $request->isGET(),
92
            'GET with invalid POST method override'
93
        );
94
95
        $request = new HTTPRequest(
96
            'POST',
97
            'admin/crm',
98
            [],
99
            ['_method' => 'DELETE']
100
        );
101
102
        $this->assertTrue(
103
            $request->isPOST(),
104
            '_method override is no longer honored'
105
        );
106
107
        $this->assertFalse(
108
            $request->isDELETE(),
109
            'DELETE _method override is not honored'
110
        );
111
112
        $request = new HTTPRequest(
113
            'POST',
114
            'admin/crm',
115
            [],
116
            ['_method' => 'put']
117
        );
118
        $this->assertFalse(
119
            $request->isPUT(),
120
            'PUT _method override is not honored'
121
        );
122
123
        $request = new HTTPRequest(
124
            'POST',
125
            'admin/crm',
126
            [],
127
            ['_method' => 'head']
128
        );
129
        $this->assertFalse(
130
            $request->isHEAD(),
131
            'HEAD _method override is not honored'
132
        );
133
    }
134
135
    public function detectMethodDataProvider()
136
    {
137
        return [
138
            'Plain POST request' => ['POST', [], 'POST'],
139
            'Plain GET request' => ['GET', [], 'GET'],
140
            'Plain DELETE request' => ['DELETE', [], 'DELETE'],
141
            'Plain PUT request' => ['PUT', [], 'PUT'],
142
            'Plain HEAD request' => ['HEAD', [], 'HEAD'],
143
144
            'Request with GET method override' => ['POST', ['_method' => 'GET'], 'GET'],
145
            'Request with HEAD method override' => ['POST', ['_method' => 'HEAD'], 'HEAD'],
146
            'Request with DELETE method override' => ['POST', ['_method' => 'DELETE'], 'DELETE'],
147
            'Request with PUT method override' => ['POST', ['_method' => 'PUT'], 'PUT'],
148
            'Request with POST method override' => ['POST', ['_method' => 'POST'], 'POST'],
149
150
            'Request with mixed case method override' => ['POST', ['_method' => 'gEt'], 'GET']
151
        ];
152
    }
153
154
    /**
155
     * @dataProvider detectMethodDataProvider
156
     */
157
    public function testDetectMethod($realMethod, $post, $expected)
158
    {
159
        $actual = HTTPRequest::detect_method($realMethod, $post);
0 ignored issues
show
Deprecated Code introduced by
The function SilverStripe\Control\HTTPRequest::detect_method() has been deprecated: 4.4.7 ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

159
        $actual = /** @scrutinizer ignore-deprecated */ HTTPRequest::detect_method($realMethod, $post);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
160
        $this->assertEquals($expected, $actual);
161
    }
162
163
    /**
164
     * @expectedException PHPUnit_Framework_Error
165
     */
166
    public function testBadDetectMethod()
167
    {
168
        HTTPRequest::detect_method('POST', ['_method' => 'Boom']);
0 ignored issues
show
Deprecated Code introduced by
The function SilverStripe\Control\HTTPRequest::detect_method() has been deprecated: 4.4.7 ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

168
        /** @scrutinizer ignore-deprecated */ HTTPRequest::detect_method('POST', ['_method' => 'Boom']);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
169
    }
170
171
    public function setHttpMethodDataProvider()
172
    {
173
        return [
174
            'POST request' => ['POST','POST'],
175
            'GET request' => ['GET', 'GET'],
176
            'DELETE request' => ['DELETE', 'DELETE'],
177
            'PUT request' => ['PUT', 'PUT'],
178
            'HEAD request' => ['HEAD', 'HEAD'],
179
            'Mixed case POST' => ['gEt', 'GET'],
180
        ];
181
    }
182
183
    /**
184
     * @dataProvider setHttpMethodDataProvider
185
     */
186
    public function testSetHttpMethod($method, $expected)
187
    {
188
        $request = new HTTPRequest('GET', '/hello');
189
        $returnedRequest  = $request->setHttpMethod($method);
190
        $this->assertEquals($expected, $request->httpMethod());
191
        $this->assertEquals($request, $returnedRequest);
192
    }
193
194
    /**
195
     * @expectedException PHPUnit_Framework_Error
196
     */
197
    public function testBadSetHttpMethod()
198
    {
199
        $request = new HTTPRequest('GET', '/hello');
200
        $request->setHttpMethod('boom');
201
    }
202
203
    public function testRequestVars()
204
    {
205
        $getVars = [
206
            'first' => 'a',
207
            'second' => 'b',
208
        ];
209
        $postVars = [
210
            'third' => 'c',
211
            'fourth' => 'd',
212
        ];
213
        $requestVars = [
214
            'first' => 'a',
215
            'second' => 'b',
216
            'third' => 'c',
217
            'fourth' => 'd',
218
        ];
219
        $request = new HTTPRequest(
220
            'POST',
221
            'admin/crm',
222
            $getVars,
223
            $postVars
224
        );
225
        $this->assertEquals(
226
            $requestVars,
227
            $request->requestVars(),
228
            'GET parameters should supplement POST parameters'
229
        );
230
231
        $getVars = [
232
            'first' => 'a',
233
            'second' => 'b',
234
        ];
235
        $postVars = [
236
            'first' => 'c',
237
            'third' => 'd',
238
        ];
239
        $requestVars = [
240
            'first' => 'c',
241
            'second' => 'b',
242
            'third' => 'd',
243
        ];
244
        $request = new HTTPRequest(
245
            'POST',
246
            'admin/crm',
247
            $getVars,
248
            $postVars
249
        );
250
        $this->assertEquals(
251
            $requestVars,
252
            $request->requestVars(),
253
            'POST parameters should override GET parameters'
254
        );
255
256
        $getVars = [
257
            'first' => [
258
                'first' => 'a',
259
            ],
260
            'second' => [
261
                'second' => 'b',
262
            ],
263
        ];
264
        $postVars = [
265
            'first' => [
266
                'first' => 'c',
267
            ],
268
            'third' => [
269
                'third' => 'd',
270
            ],
271
        ];
272
        $requestVars = [
273
            'first' => [
274
                'first' => 'c',
275
            ],
276
            'second' => [
277
                'second' => 'b',
278
            ],
279
            'third' => [
280
                'third' => 'd',
281
            ],
282
        ];
283
        $request = new HTTPRequest(
284
            'POST',
285
            'admin/crm',
286
            $getVars,
287
            $postVars
288
        );
289
        $this->assertEquals(
290
            $requestVars,
291
            $request->requestVars(),
292
            'Nested POST parameters should override GET parameters'
293
        );
294
295
        $getVars = [
296
            'first' => [
297
                'first' => 'a',
298
            ],
299
            'second' => [
300
                'second' => 'b',
301
            ],
302
        ];
303
        $postVars = [
304
            'first' => [
305
                'second' => 'c',
306
            ],
307
            'third' => [
308
                'third' => 'd',
309
            ],
310
        ];
311
        $requestVars = [
312
            'first' => [
313
                'first' => 'a',
314
                'second' => 'c',
315
            ],
316
            'second' => [
317
                'second' => 'b',
318
            ],
319
            'third' => [
320
                'third' => 'd',
321
            ],
322
        ];
323
        $request = new HTTPRequest(
324
            'POST',
325
            'admin/crm',
326
            $getVars,
327
            $postVars
328
        );
329
        $this->assertEquals(
330
            $requestVars,
331
            $request->requestVars(),
332
            'Nested GET parameters should supplement POST parameters'
333
        );
334
    }
335
336
    public function testIsAjax()
337
    {
338
        $req = new HTTPRequest('GET', '/', ['ajax' => 0]);
339
        $this->assertFalse($req->isAjax());
340
341
        $req = new HTTPRequest('GET', '/', ['ajax' => 1]);
342
        $this->assertTrue($req->isAjax());
343
344
        $req = new HTTPRequest('GET', '/');
345
        $req->addHeader('X-Requested-With', 'XMLHttpRequest');
346
        $this->assertTrue($req->isAjax());
347
    }
348
349
    public function testGetURL()
350
    {
351
        $req = new HTTPRequest('GET', '/');
352
        $this->assertEquals('', $req->getURL());
353
354
        $req = new HTTPRequest('GET', '/assets/somefile.gif');
355
        $this->assertEquals('assets/somefile.gif', $req->getURL());
356
357
        $req = new HTTPRequest('GET', '/home?test=1');
358
        $this->assertEquals('home?test=1', $req->getURL(true));
359
        $this->assertEquals('home', $req->getURL());
360
    }
361
362
    public function testSetIPFromHeaderValue()
363
    {
364
        $req = new TrustedProxyMiddleware();
365
        $reflectionMethod = new ReflectionMethod($req, 'getIPFromHeaderValue');
366
        $reflectionMethod->setAccessible(true);
367
368
        $headers = [
369
            '80.79.208.21, 149.126.76.1, 10.51.0.68' => '80.79.208.21',
370
            '52.19.19.103, 10.51.0.49' => '52.19.19.103',
371
            '10.51.0.49, 52.19.19.103' => '52.19.19.103',
372
            '10.51.0.49' => '10.51.0.49',
373
            '127.0.0.1, 10.51.0.49' => '127.0.0.1',
374
        ];
375
376
        foreach ($headers as $header => $ip) {
377
            $this->assertEquals($ip, $reflectionMethod->invoke($req, $header));
378
        }
379
    }
380
381
    public function testHasSession()
382
    {
383
        $request = new HTTPRequest('GET', '/');
384
        $this->assertFalse($request->hasSession());
385
386
        $request->setSession($this->createMock(Session::class));
387
        $this->assertTrue($request->hasSession());
388
    }
389
}
390