Content-Length: 826608 | pFad | http://github.com/symfony/symfony/commit/0cfd34fac87d1b47854fac0f1becfd5788084f3c

C0 [HttpFoundation][HttpKernel] Add support for the `QUERY` HTTP method · symfony/symfony@0cfd34f · GitHub
Skip to content

Commit 0cfd34f

Browse files
[HttpFoundation][HttpKernel] Add support for the QUERY HTTP method
1 parent b065b9a commit 0cfd34f

File tree

7 files changed

+170
-4
lines changed

7 files changed

+170
-4
lines changed

src/Symfony/Component/HttpFoundation/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ CHANGELOG
55
---
66

77
* Deprecate using `Request::sendHeaders()` after headers have already been sent; use a `StreamedResponse` instead
8+
* Add support for the `QUERY` HTTP method
89

910
7.3
1011
---

src/Symfony/Component/HttpFoundation/Request.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ class Request
6262
public const METHOD_OPTIONS = 'OPTIONS';
6363
public const METHOD_TRACE = 'TRACE';
6464
public const METHOD_CONNECT = 'CONNECT';
65+
public const METHOD_QUERY = 'QUERY';
6566

6667
/**
6768
* @var string[]
@@ -1351,15 +1352,15 @@ public function isMethod(string $method): bool
13511352
*/
13521353
public function isMethodSafe(): bool
13531354
{
1354-
return \in_array($this->getMethod(), ['GET', 'HEAD', 'OPTIONS', 'TRACE'], true);
1355+
return \in_array($this->getMethod(), ['GET', 'HEAD', 'OPTIONS', 'TRACE', 'QUERY'], true);
13551356
}
13561357

13571358
/**
13581359
* Checks whether or not the method is idempotent.
13591360
*/
13601361
public function isMethodIdempotent(): bool
13611362
{
1362-
return \in_array($this->getMethod(), ['HEAD', 'GET', 'PUT', 'DELETE', 'TRACE', 'OPTIONS', 'PURGE'], true);
1363+
return \in_array($this->getMethod(), ['HEAD', 'GET', 'PUT', 'DELETE', 'TRACE', 'OPTIONS', 'PURGE', 'QUERY'], true);
13631364
}
13641365

13651366
/**
@@ -1369,7 +1370,7 @@ public function isMethodIdempotent(): bool
13691370
*/
13701371
public function isMethodCacheable(): bool
13711372
{
1372-
return \in_array($this->getMethod(), ['GET', 'HEAD'], true);
1373+
return \in_array($this->getMethod(), ['GET', 'HEAD', 'QUERY'], true);
13731374
}
13741375

13751376
/**

src/Symfony/Component/HttpFoundation/Tests/RequestTest.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2330,6 +2330,7 @@ public static function methodIdempotentProvider()
23302330
['OPTIONS', true],
23312331
['TRACE', true],
23322332
['CONNECT', false],
2333+
['QUERY', true],
23332334
];
23342335
}
23352336

@@ -2356,6 +2357,7 @@ public static function methodSafeProvider()
23562357
['OPTIONS', true],
23572358
['TRACE', true],
23582359
['CONNECT', false],
2360+
['QUERY', true],
23592361
];
23602362
}
23612363

@@ -2382,6 +2384,7 @@ public static function methodCacheableProvider()
23822384
['OPTIONS', false],
23832385
['TRACE', false],
23842386
['CONNECT', false],
2387+
['QUERY', true],
23852388
];
23862389
}
23872390

src/Symfony/Component/HttpKernel/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
7.4
5+
---
6+
7+
* Add support for the `QUERY` HTTP method
8+
49
7.3
510
---
611

src/Symfony/Component/HttpKernel/HttpCache/Store.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,13 @@ public function getPath(string $key): string
427427
*/
428428
protected function generateCacheKey(Request $request): string
429429
{
430-
return 'md'.hash('sha256', $request->getUri());
430+
$key = $request->getUri();
431+
432+
if ('QUERY' === $request->getMethod()) {
433+
$key .= $request->getContent();
434+
}
435+
436+
return 'md'.hash('sha256', $key);
431437
}
432438

433439
/**

src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2070,6 +2070,92 @@ public function testTraceLevelShort()
20702070
$this->assertTrue($this->response->headers->has('X-Symfony-Cache'));
20712071
$this->assertEquals('miss', $this->response->headers->get('X-Symfony-Cache'));
20722072
}
2073+
2074+
public function testQueryMethodIsCacheable()
2075+
{
2076+
$this->setNextResponse(200, ['Cache-Control' => 'public, max-age=10000'], 'Query result', function (Request $request) {
2077+
$this->assertSame('QUERY', $request->getMethod());
2078+
return '{"query": "users"}' === $request->getContent();
2079+
});
2080+
2081+
$this->kernel->reset();
2082+
$this->store = $this->createStore();
2083+
$this->cacheConfig['debug'] = true;
2084+
$this->cache = new HttpCache($this->kernel, $this->store, null, $this->cacheConfig);
2085+
2086+
$request1 = Request::create('/', 'QUERY', [], [], [], [], '{"query": "users"}');
2087+
$this->response = $this->cache->handle($request1, HttpKernelInterface::MAIN_REQUEST, $this->catch);
2088+
2089+
$this->assertSame(200, $this->response->getStatusCode());
2090+
$this->assertTraceContains('miss');
2091+
$this->assertSame('Query result', $this->response->getContent());
2092+
2093+
$request2 = Request::create('/', 'QUERY', [], [], [], [], '{"query": "users"}');
2094+
$this->response = $this->cache->handle($request2, HttpKernelInterface::MAIN_REQUEST, $this->catch);
2095+
2096+
$this->assertSame(200, $this->response->getStatusCode());
2097+
$this->assertTrue($this->response->headers->has('Age'));
2098+
$this->assertSame('Query result', $this->response->getContent());
2099+
}
2100+
2101+
public function testQueryMethodDifferentBodiesCreateDifferentCacheEntries()
2102+
{
2103+
$this->setNextResponses([
2104+
[
2105+
'status' => 200,
2106+
'body' => 'Users result',
2107+
'headers' => ['Cache-Control' => 'public, max-age=10000'],
2108+
],
2109+
[
2110+
'status' => 200,
2111+
'body' => 'Posts result',
2112+
'headers' => ['Cache-Control' => 'public, max-age=10000'],
2113+
],
2114+
]);
2115+
2116+
$this->store = $this->createStore();
2117+
$this->cacheConfig['debug'] = true;
2118+
$this->cache = new HttpCache($this->kernel, $this->store, null, $this->cacheConfig);
2119+
2120+
$request1 = Request::create('/', 'QUERY', [], [], [], [], '{"query": "users"}');
2121+
$this->response = $this->cache->handle($request1, HttpKernelInterface::MAIN_REQUEST, $this->catch);
2122+
2123+
$this->assertSame('Users result', $this->response->getContent());
2124+
$this->assertTraceContains('miss');
2125+
2126+
$request2 = Request::create('/', 'QUERY', [], [], [], [], '{"query": "posts"}');
2127+
$this->response = $this->cache->handle($request2, HttpKernelInterface::MAIN_REQUEST, $this->catch);
2128+
2129+
$this->assertSame('Posts result', $this->response->getContent());
2130+
$this->assertTraceContains('miss');
2131+
2132+
$request3 = Request::create('/', 'QUERY', [], [], [], [], '{"query": "users"}');
2133+
$this->response = $this->cache->handle($request3, HttpKernelInterface::MAIN_REQUEST, $this->catch);
2134+
2135+
$this->assertSame('Users result', $this->response->getContent());
2136+
$this->assertTrue($this->response->headers->has('Age'));
2137+
}
2138+
2139+
public function testQueryMethodWithEmptyBodyIsCacheable()
2140+
{
2141+
$this->setNextResponse(200, ['Cache-Control' => 'public, max-age=10000'], 'Empty query result');
2142+
$this->kernel->reset();
2143+
$this->store = $this->createStore();
2144+
$this->cacheConfig['debug'] = true;
2145+
$this->cache = new HttpCache($this->kernel, $this->store, null, $this->cacheConfig);
2146+
2147+
$request1 = Request::create('/', 'QUERY', [], [], [], [], '');
2148+
$this->response = $this->cache->handle($request1, HttpKernelInterface::MAIN_REQUEST, $this->catch);
2149+
2150+
$this->assertSame(200, $this->response->getStatusCode());
2151+
$this->assertTraceContains('miss');
2152+
2153+
$request2 = Request::create('/', 'QUERY', [], [], [], [], '');
2154+
$this->response = $this->cache->handle($request2, HttpKernelInterface::MAIN_REQUEST, $this->catch);
2155+
2156+
$this->assertSame(200, $this->response->getStatusCode());
2157+
$this->assertTrue($this->response->headers->has('Age'));
2158+
}
20732159
}
20742160

20752161
class TestKernel implements HttpKernelInterface

src/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,4 +378,68 @@ protected function getStorePath($key)
378378

379379
return $m->invoke($this->store, $key);
380380
}
381+
382+
public function testQueryMethodCacheKeyIncludesBody()
383+
{
384+
$response = new Response('test', 200, ['Cache-Control' => 'max-age=420']);
385+
386+
$request1 = Request::create('/', 'QUERY', [], [], [], [], '{"query": "users"}');
387+
$request2 = Request::create('/', 'QUERY', [], [], [], [], '{"query": "posts"}');
388+
$request3 = Request::create('/', 'QUERY', [], [], [], [], '{"query": "users"}');
389+
390+
$key1 = $this->store->write($request1, $response);
391+
$key2 = $this->store->write($request2, $response);
392+
$key3 = $this->store->write($request3, $response);
393+
394+
$this->assertNotSame($key1, $key2);
395+
$this->assertSame($key1, $key3);
396+
397+
$this->assertNotEmpty($this->getStoreMetadata($key1));
398+
$this->assertNotEmpty($this->getStoreMetadata($key2));
399+
400+
$this->assertNotNull($this->store->lookup($request1));
401+
$this->assertNotNull($this->store->lookup($request2));
402+
$this->assertNotNull($this->store->lookup($request3));
403+
}
404+
405+
public function testQueryMethodCacheKeyDiffersFromGet()
406+
{
407+
$response = new Response('test', 200, ['Cache-Control' => 'max-age=420']);
408+
409+
$getRequest = Request::create('/');
410+
$queryRequest = Request::create('/', 'QUERY', [], [], [], [], '{"query": "test"}');
411+
412+
$getKey = $this->store->write($getRequest, $response);
413+
$queryKey = $this->store->write($queryRequest, $response);
414+
415+
$this->assertNotSame($getKey, $queryKey);
416+
417+
$this->assertNotEmpty($this->getStoreMetadata($getKey));
418+
$this->assertNotEmpty($this->getStoreMetadata($queryKey));
419+
420+
$this->assertNotNull($this->store->lookup($getRequest));
421+
$this->assertNotNull($this->store->lookup($queryRequest));
422+
}
423+
424+
public function testOtherMethodsCacheKeyIgnoresBody()
425+
{
426+
$response1 = new Response('test 1', 200, ['Cache-Control' => 'max-age=420']);
427+
$response2 = new Response('test 2', 200, ['Cache-Control' => 'max-age=420']);
428+
429+
$getRequest1 = Request::create('/', 'GET', [], [], [], [], '{"data": "test"}');
430+
$getRequest2 = Request::create('/', 'GET', [], [], [], [], '{"data": "different"}');
431+
432+
$key1 = $this->store->write($getRequest1, $response1);
433+
$key2 = $this->store->write($getRequest2, $response2);
434+
435+
$this->assertSame($key1, $key2);
436+
437+
$lookup1 = $this->store->lookup($getRequest1);
438+
$lookup2 = $this->store->lookup($getRequest2);
439+
$this->assertNotNull($lookup1);
440+
$this->assertNotNull($lookup2);
441+
442+
$this->assertCount(1, $this->getStoreMetadata($key1));
443+
$this->assertSame($lookup1->getContent(), $lookup2->getContent());
444+
}
381445
}

0 commit comments

Comments
 (0)








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/symfony/symfony/commit/0cfd34fac87d1b47854fac0f1becfd5788084f3c

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy