Skip to content

Commit 894cbac

Browse files
committed
Updated test case for method spoofing
1 parent bf7eee3 commit 894cbac

File tree

2 files changed

+124
-207
lines changed

2 files changed

+124
-207
lines changed
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tempest\Http\Tests\Mappers;
6+
7+
use Laminas\Diactoros\ServerRequest;
8+
use Laminas\Diactoros\Stream;
9+
use PHPUnit\Framework\Attributes\DataProvider;
10+
use PHPUnit\Framework\TestCase;
11+
use Psr\Http\Message\ServerRequestInterface;
12+
use ReflectionClass;
13+
use ReflectionMethod;
14+
use Tempest\Cryptography\Encryption\Encrypter;
15+
use Tempest\Http\Mappers\PsrRequestToGenericRequestMapper;
16+
use Tempest\Http\Method;
17+
18+
final class PsrRequestToGenericRequestMapperTest extends TestCase
19+
{
20+
private PsrRequestToGenericRequestMapper $mapper;
21+
private Encrypter $encrypter;
22+
private ReflectionMethod $requestMethod;
23+
24+
protected function setUp(): void
25+
{
26+
parent::setUp();
27+
28+
$this->encrypter = $this->createMock(Encrypter::class);
29+
$this->encrypter->method('decrypt')->willReturnArgument(0);
30+
31+
$this->mapper = new PsrRequestToGenericRequestMapper($this->encrypter);
32+
33+
$reflection = new ReflectionClass($this->mapper);
34+
$this->requestMethod = $reflection->getMethod('requestMethod');
35+
$this->requestMethod->setAccessible(true);
36+
}
37+
38+
#[DataProvider('nonPostMethodsProvider')]
39+
public function test_non_post_requests_are_not_affected_by_method_param(string $originalMethod): void
40+
{
41+
$request = $this->createServerRequest(
42+
$originalMethod,
43+
['_method' => 'DELETE'],
44+
);
45+
46+
$method = $this->requestMethod->invoke($this->mapper, $request, ['_method' => 'DELETE']);
47+
48+
$this->assertSame(Method::from($originalMethod), $method);
49+
}
50+
51+
#[DataProvider('validSpoofedMethodsProvider')]
52+
public function test_post_with_valid_method_is_spoofed(string $spoofedMethod): void
53+
{
54+
$request = $this->createServerRequest(
55+
'POST',
56+
['_method' => $spoofedMethod],
57+
);
58+
59+
$method = $this->requestMethod->invoke($this->mapper, $request, ['_method' => $spoofedMethod]);
60+
61+
$this->assertSame(Method::from(strtoupper($spoofedMethod)), $method);
62+
}
63+
64+
public function test_post_with_invalid_method_is_not_spoofed(): void
65+
{
66+
$request = $this->createServerRequest(
67+
'POST',
68+
['_method' => 'INVALID'],
69+
);
70+
71+
$method = $this->requestMethod->invoke($this->mapper, $request, ['_method' => 'INVALID']);
72+
73+
$this->assertSame(Method::POST, $method);
74+
}
75+
76+
public function test_method_param_is_case_insensitive(): void
77+
{
78+
$request = $this->createServerRequest(
79+
'POST',
80+
['_method' => 'delete'],
81+
);
82+
83+
$method = $this->requestMethod->invoke($this->mapper, $request, ['_method' => 'delete']);
84+
85+
$this->assertSame(Method::DELETE, $method);
86+
}
87+
88+
public static function nonPostMethodsProvider(): array
89+
{
90+
return [
91+
['GET'],
92+
['PUT'],
93+
['PATCH'],
94+
['DELETE'],
95+
['HEAD'],
96+
['OPTIONS'],
97+
['TRACE'],
98+
['CONNECT'],
99+
];
100+
}
101+
102+
public static function validSpoofedMethodsProvider(): array
103+
{
104+
return [
105+
['PUT'],
106+
['PATCH'],
107+
['DELETE'],
108+
];
109+
}
110+
111+
private function createServerRequest(string $method, array $body = []): ServerRequestInterface
112+
{
113+
$request = new ServerRequest([], [], '/', $method);
114+
115+
if (! empty($body)) {
116+
$request = $request->withParsedBody($body);
117+
}
118+
119+
$stream = new Stream('php://temp', 'r+');
120+
$request = $request->withBody($stream);
121+
122+
return $request;
123+
}
124+
}

packages/http/tests/MethodSpoofingTest.php

Lines changed: 0 additions & 207 deletions
This file was deleted.

0 commit comments

Comments
 (0)