Completed
Pull Request — master (#43)
by
unknown
09:01 queued 07:19
created

testCanHandleUnconfiguredRouteMatch()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 23
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 23
rs 9.0856
cc 1
eloc 16
nc 1
nop 0
1
<?php
2
/*
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the MIT license.
17
 */
18
19
namespace ZfrCorsTest\Mvc;
20
21
use PHPUnit_Framework_TestCase as TestCase;
22
use Zend\Http\Response as HttpResponse;
23
use Zend\Http\Request as HttpRequest;
24
use Zend\Mvc\MvcEvent;
25
use Zend\Mvc\Router\Http\RouteMatch;
26
use ZfrCors\Options\CorsOptions;
27
use ZfrCors\Service\CorsService;
28
29
/**
30
 * Integration tests for {@see \ZfrCors\Service\CorsService}
31
 *
32
 * @author Florent Blaison <[email protected]>
33
 *
34
 * @covers \ZfrCors\Service\CorsService
35
 * @group Coverage
36
 */
37
class CorsServiceTest extends TestCase
38
{
39
    /**
40
     * @var CorsService
41
     */
42
    protected $corsService;
43
44
    /**
45
     * @var HttpResponse
46
     */
47
    protected $response;
48
49
    /**
50
     * @var HttpRequest
51
     */
52
    protected $request;
53
54
    /**
55
     * @var MvcEvent
56
     */
57
    protected $event;
58
59
    /**
60
     * @var CorsOptions
61
     */
62
    protected $corsOptions;
63
64
    /**
65
     * Set up
66
     */
67
    public function setUp()
68
    {
69
        parent::setUp();
70
71
        $this->corsOptions = new CorsOptions(
72
            [
73
                'allowed_origins'     => ['http://example.com'],
74
                'allowed_methods'     => ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
75
                'allowed_headers'     => ['Content-Type', 'Accept'],
76
                'exposed_headers'     => ['Location'],
77
                'max_age'             => 10,
78
                'allowed_credentials' => true,
79
            ]
80
        );
81
82
        $this->corsService = new CorsService($this->corsOptions);
83
    }
84
85
    public function testCanDetectCorsRequest()
86
    {
87
        $request = new HttpRequest();
88
89
        $this->assertFalse($this->corsService->isCorsRequest($request));
90
91
        $request->getHeaders()->addHeaderLine('Origin', 'http://example.com');
92
        $this->assertEquals(true, $this->corsService->isCorsRequest($request));
93
    }
94
95
    public function testIsNotCorsRequestIfNotACrossRequest()
96
    {
97
        $request = new HttpRequest();
98
        $request->setUri('http://example.com');
99
100
        $request->getHeaders()->addHeaderLine('Origin', 'http://example.com');
101
        $this->assertEquals(false, $this->corsService->isCorsRequest($request));
102
    }
103
104
    public function testCanDetectPreflightRequest()
105
    {
106
        $request = new HttpRequest();
107
108
        $this->assertFalse($this->corsService->isPreflightRequest($request));
109
110
        $request->setMethod('OPTIONS');
111
        $this->assertFalse($this->corsService->isPreflightRequest($request));
112
113
        $request->getHeaders()->addHeaderLine('Origin', 'http://example.com');
114
        $this->assertFalse($this->corsService->isPreflightRequest($request));
115
116
        $request->getHeaders()->addHeaderLine('Access-Control-Request-Method', 'POST');
117
        $this->assertTrue($this->corsService->isPreflightRequest($request));
118
    }
119
120
    public function testProperlyCreatePreflightResponse()
121
    {
122
        $request  = new HttpRequest();
123
        $request->getHeaders()->addHeaderLine('Origin', 'http://example.com');
124
125
        $response = $this->corsService->createPreflightCorsResponse($request);
126
127
        $headers = $response->getHeaders();
128
129
        $this->assertEquals(200, $response->getStatusCode());
130
        $this->assertEquals('', $response->getContent());
131
        $this->assertEquals('http://example.com', $headers->get('Access-Control-Allow-Origin')->getFieldValue());
0 ignored issues
show
Bug introduced by
The method getFieldValue does only exist in Zend\Http\Header\HeaderInterface, but not in ArrayIterator.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
132
        $this->assertEquals(
133
            'GET, POST, PUT, DELETE, OPTIONS',
134
            $headers->get('Access-Control-Allow-Methods')->getFieldValue()
135
        );
136
        $this->assertEquals('Content-Type, Accept', $headers->get('Access-Control-Allow-Headers')->getFieldValue());
137
        $this->assertEquals(10, $headers->get('Access-Control-Max-Age')->getFieldValue());
138
        $this->assertEquals(0, $headers->get('Content-Length')->getFieldValue());
139
140
        $this->assertEquals('true', $headers->get('Access-Control-Allow-Credentials')->getFieldValue());
141
    }
142
143
    public function testDoesNotAddAllowCredentialsHeadersIfAsked()
144
    {
145
        $request  = new HttpRequest();
146
        $request->getHeaders()->addHeaderLine('Origin', 'http://example.com');
147
        $this->corsOptions->setAllowedCredentials(false);
148
149
        $response = $this->corsService->createPreflightCorsResponse($request);
150
151
        $headers = $response->getHeaders();
152
        $this->assertFalse($headers->has('Access-Control-Allow-Credentials'));
153
    }
154
155
    public function testCanReturnWildCardAllowOrigin()
156
    {
157
        $request  = new HttpRequest();
158
        $request->getHeaders()->addHeaderLine('Origin', 'http://funny-origin.com');
159
        $this->corsOptions->setAllowedOrigins(['*']);
160
161
        $response = $this->corsService->createPreflightCorsResponse($request);
162
163
        $headers = $response->getHeaders();
164
        $this->assertEquals('*', $headers->get('Access-Control-Allow-Origin')->getFieldValue());
0 ignored issues
show
Bug introduced by
The method getFieldValue does only exist in Zend\Http\Header\HeaderInterface, but not in ArrayIterator.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
165
    }
166
167
    public function testCanReturnWildCardSubDomainAllowOrigin()
168
    {
169
        $request  = new HttpRequest();
170
        $request->getHeaders()->addHeaderLine('Origin', 'http://subdomain.example.com');
171
        $this->corsOptions->setAllowedOrigins(['*.example.com']);
172
173
        $response = $this->corsService->createPreflightCorsResponse($request);
174
175
        $headers = $response->getHeaders();
176
        $headerValue = $headers->get('Access-Control-Allow-Origin')->getFieldValue();
0 ignored issues
show
Bug introduced by
The method getFieldValue does only exist in Zend\Http\Header\HeaderInterface, but not in ArrayIterator.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
177
        $this->assertEquals('http://subdomain.example.com', $headerValue);
178
    }
179
180
    public function testCanReturnWildCardSubDomainWithSchemeAllowOrigin()
181
    {
182
        $request  = new HttpRequest();
183
        $request->getHeaders()->addHeaderLine('Origin', 'https://subdomain.example.com');
184
        $this->corsOptions->setAllowedOrigins(['https://*.example.com']);
185
186
        $response = $this->corsService->createPreflightCorsResponse($request);
187
188
        $headers = $response->getHeaders();
189
        $headerValue = $headers->get('Access-Control-Allow-Origin')->getFieldValue();
0 ignored issues
show
Bug introduced by
The method getFieldValue does only exist in Zend\Http\Header\HeaderInterface, but not in ArrayIterator.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
190
        $this->assertEquals('https://subdomain.example.com', $headerValue);
191
    }
192
193
    public function testReturnNullForMissMatchedWildcardSubDomainOrigin()
194
    {
195
        $request  = new HttpRequest();
196
        $request->getHeaders()->addHeaderLine('Origin', 'http://subdomain.example.org');
197
        $this->corsOptions->setAllowedOrigins(['*.example.com']);
198
199
        $response = $this->corsService->createPreflightCorsResponse($request);
200
201
        $headers = $response->getHeaders();
202
        $this->assertEquals('null', $headers->get('Access-Control-Allow-Origin')->getFieldValue());
0 ignored issues
show
Bug introduced by
The method getFieldValue does only exist in Zend\Http\Header\HeaderInterface, but not in ArrayIterator.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
203
    }
204
205
    public function testReturnNullForRootDomainOnWildcardSubDomainOrigin()
206
    {
207
        $request  = new HttpRequest();
208
        $request->getHeaders()->addHeaderLine('Origin', 'http://example.com');
209
        $this->corsOptions->setAllowedOrigins(['*.example.com']);
210
211
        $response = $this->corsService->createPreflightCorsResponse($request);
212
213
        $headers = $response->getHeaders();
214
        $this->assertEquals('null', $headers->get('Access-Control-Allow-Origin')->getFieldValue());
0 ignored issues
show
Bug introduced by
The method getFieldValue does only exist in Zend\Http\Header\HeaderInterface, but not in ArrayIterator.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
215
    }
216
217
    public function testReturnNullForDifferentSchemeOnWildcardSubDomainOrigin()
218
    {
219
        $request  = new HttpRequest();
220
        $request->getHeaders()->addHeaderLine('Origin', 'https://example.com');
221
        $this->corsOptions->setAllowedOrigins(['http://*.example.com']);
222
223
        $response = $this->corsService->createPreflightCorsResponse($request);
224
225
        $headers = $response->getHeaders();
226
        $this->assertEquals('null', $headers->get('Access-Control-Allow-Origin')->getFieldValue());
0 ignored issues
show
Bug introduced by
The method getFieldValue does only exist in Zend\Http\Header\HeaderInterface, but not in ArrayIterator.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
227
    }
228
229
    public function testReturnNullForUnknownOrigin()
230
    {
231
        $request  = new HttpRequest();
232
        $request->getHeaders()->addHeaderLine('Origin', 'http://unauthorized-origin.com');
233
234
        $response = $this->corsService->createPreflightCorsResponse($request);
235
236
        $headers = $response->getHeaders();
237
        $this->assertEquals('null', $headers->get('Access-Control-Allow-Origin')->getFieldValue());
0 ignored issues
show
Bug introduced by
The method getFieldValue does only exist in Zend\Http\Header\HeaderInterface, but not in ArrayIterator.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
238
    }
239
240
    public function testEnsureVaryHeaderForNoOrigin()
241
    {
242
        $response = new HttpResponse();
243
244
        $this->corsService->ensureVaryHeader($response);
245
246
        $headers = $response->getHeaders();
247
248
        $this->assertEquals(false, $headers->get('Origin'));
249
        $this->assertNotEquals(false, $headers->get('Vary'));
250
    }
251
252
    public function testCanPopulateNormalCorsRequest()
253
    {
254
        $request  = new HttpRequest();
255
        $response = new HttpResponse();
256
257
        $request->getHeaders()->addHeaderLine('Origin', 'http://example.com');
258
259
        $this->corsService->populateCorsResponse($request, $response);
260
261
        $headers = $response->getHeaders();
262
263
        $this->assertEquals('http://example.com', $headers->get('Access-Control-Allow-Origin')->getFieldValue());
0 ignored issues
show
Bug introduced by
The method getFieldValue does only exist in Zend\Http\Header\HeaderInterface, but not in ArrayIterator.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
264
        $this->assertEquals('Location', $headers->get('Access-Control-Expose-Headers')->getFieldValue());
265
    }
266
267
    public function testRefuseNormalCorsRequestIfUnauthorized()
268
    {
269
        $request  = new HttpRequest();
270
        $response = new HttpResponse();
271
272
        $request->getHeaders()->addHeaderLine('Origin', 'http://unauthorized.com');
273
274
        $this->setExpectedException(
275
            'ZfrCors\Exception\DisallowedOriginException',
276
            'The origin "http://unauthorized.com" is not authorized'
277
        );
278
279
        $this->corsService->populateCorsResponse($request, $response);
280
    }
281
282
    public function testAddVaryHeaderInNormalRequest()
283
    {
284
        $request  = new HttpRequest();
285
        $response = new HttpResponse();
286
287
        $request->getHeaders()->addHeaderLine('Origin', 'http://example.com');
288
289
        $this->corsService->populateCorsResponse($request, $response);
290
291
        $headers = $response->getHeaders();
292
        $this->assertTrue($headers->has('Vary'));
293
    }
294
295
    public function testAppendVaryHeaderInNormalRequest()
296
    {
297
        $request  = new HttpRequest();
298
        $response = new HttpResponse();
299
300
        $request->getHeaders()->addHeaderLine('Origin', 'http://example.com');
301
        $response->getHeaders()->addHeaderLine('Vary', 'Foo');
302
303
        $this->corsService->populateCorsResponse($request, $response);
304
305
        $headers = $response->getHeaders();
306
        $this->assertTrue($headers->has('Vary'));
307
        $this->assertEquals('Foo, Origin', $headers->get('Vary')->getFieldValue());
0 ignored issues
show
Bug introduced by
The method getFieldValue does only exist in Zend\Http\Header\HeaderInterface, but not in ArrayIterator.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
308
    }
309
310
    public function testPopulatesAllowCredentialsNormalCorsRequest()
311
    {
312
        $request  = new HttpRequest();
313
        $response = new HttpResponse();
314
315
        $request->getHeaders()->addHeaderLine('Origin', 'http://example.com');
316
317
        $this->corsService->populateCorsResponse($request, $response);
318
319
        $headers = $response->getHeaders();
320
321
        $this->assertEquals('true', $headers->get('Access-Control-Allow-Credentials')->getFieldValue());
0 ignored issues
show
Bug introduced by
The method getFieldValue does only exist in Zend\Http\Header\HeaderInterface, but not in ArrayIterator.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
322
    }
323
324
    public function testCanDetectCorsRequestFromSameHostButDifferentPort()
325
    {
326
        $request = new HttpRequest();
327
        $request->setUri('http://example.com');
328
        $request->getHeaders()->addHeaderLine('Origin', 'http://example.com:9000');
329
        $this->assertTrue($this->corsService->isCorsRequest($request));
330
    }
331
332
    public function testCanDetectCorsRequestFromSameHostButDifferentScheme()
333
    {
334
        $request = new HttpRequest();
335
        $request->setUri('https://example.com');
336
        $request->getHeaders()->addHeaderLine('Origin', 'http://example.com');
337
        $this->assertTrue($this->corsService->isCorsRequest($request));
338
    }
339
340
    public function testCanHandleUnconfiguredRouteMatch()
341
    {
342
        $routeMatch = new RouteMatch([]);
343
344
        $request = new HttpRequest();
345
        $request->getHeaders()->addHeaderLine('Origin', 'http://example.com');
346
        $response = $this->corsService->createPreflightCorsResponseWithRouteOptions($request, $routeMatch);
347
348
        $headers = $response->getHeaders();
349
350
        $this->assertEquals(200, $response->getStatusCode());
351
        $this->assertEquals('', $response->getContent());
352
        $this->assertEquals('http://example.com', $headers->get('Access-Control-Allow-Origin')->getFieldValue());
0 ignored issues
show
Bug introduced by
The method getFieldValue does only exist in Zend\Http\Header\HeaderInterface, but not in ArrayIterator.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
353
        $this->assertEquals(
354
            'GET, POST, PUT, DELETE, OPTIONS',
355
            $headers->get('Access-Control-Allow-Methods')->getFieldValue()
356
        );
357
        $this->assertEquals('Content-Type, Accept', $headers->get('Access-Control-Allow-Headers')->getFieldValue());
358
        $this->assertEquals(10, $headers->get('Access-Control-Max-Age')->getFieldValue());
359
        $this->assertEquals(0, $headers->get('Content-Length')->getFieldValue());
360
361
        $this->assertEquals('true', $headers->get('Access-Control-Allow-Credentials')->getFieldValue());
362
    }
363
364
    public function testCanHandleConfiguredRouteMatch()
365
    {
366
        $routeMatch = new RouteMatch([
367
            CorsOptions::ROUTE_PARAM => [
368
                'allowed_origins'     => ['http://example.org'],
369
                'allowed_methods'     => ['POST', 'DELETE', 'OPTIONS'],
370
                'allowed_headers'     => ['Content-Type', 'Accept', 'Cookie'],
371
                'exposed_headers'     => ['Location'],
372
                'max_age'             => 5,
373
                'allowed_credentials' => false,
374
            ],
375
        ]);
376
377
        $request = new HttpRequest();
378
        $request->getHeaders()->addHeaderLine('Origin', 'http://example.org');
379
        $response = $this->corsService->createPreflightCorsResponseWithRouteOptions($request, $routeMatch);
380
381
        $headers = $response->getHeaders();
382
        $this->assertEquals(200, $response->getStatusCode());
383
        $this->assertEquals('', $response->getContent());
384
        $this->assertEquals('http://example.org', $headers->get('Access-Control-Allow-Origin')->getFieldValue());
0 ignored issues
show
Bug introduced by
The method getFieldValue does only exist in Zend\Http\Header\HeaderInterface, but not in ArrayIterator.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
385
        $this->assertEquals(
386
            'POST, DELETE, OPTIONS',
387
            $headers->get('Access-Control-Allow-Methods')->getFieldValue()
388
        );
389
        $this->assertEquals('Content-Type, Accept, Cookie', $headers->get('Access-Control-Allow-Headers')->getFieldValue());
390
        $this->assertEquals(5, $headers->get('Access-Control-Max-Age')->getFieldValue());
391
        $this->assertEquals(0, $headers->get('Content-Length')->getFieldValue());
392
393
        $this->assertFalse($headers->has('Access-Control-Allow-Credentials'));
394
    }
395
}
396