minor #33725 [HttpFoundation] optimize normalization of headers (nicolas-grekas)

This PR was merged into the 4.4 branch.

Discussion
----------

[HttpFoundation] optimize normalization of headers

| Q             | A
| ------------- | ---
| Branch?       | 4.4
| Bug fix?      | no
| New feature?  | no
| Deprecations? | no
| Tickets       | -
| License       | MIT
| Doc PR        | -

I was experimenting with using maps to bypass calls to normalization functions, but that didn't lead to any significant perf improvement.

I still found this, the new call is twice as fast :)

Commits
-------

9c676d37a0 [HttpFoundation] optimize normalization of headers
This commit is contained in:
Fabien Potencier 2019-09-27 07:33:30 +02:00
commit 7a3bfac209
4 changed files with 13 additions and 15 deletions

View File

@ -18,6 +18,9 @@ namespace Symfony\Component\HttpFoundation;
*/
class HeaderBag implements \IteratorAggregate, \Countable
{
protected const UPPER = '_ABCDEFGHIJKLMNOPQRSTUVWXYZ';
protected const LOWER = '-abcdefghijklmnopqrstuvwxyz';
protected $headers = [];
protected $cacheControl = [];
@ -62,9 +65,7 @@ class HeaderBag implements \IteratorAggregate, \Countable
public function all(/*string $key = null*/)
{
if (1 <= \func_num_args() && null !== $key = func_get_arg(0)) {
$key = str_replace('_', '-', strtolower($key));
return $this->headers[$key] ?? [];
return $this->headers[strtr($key, self::UPPER, self::LOWER)] ?? [];
}
return $this->headers;
@ -138,7 +139,7 @@ class HeaderBag implements \IteratorAggregate, \Countable
*/
public function set($key, $values, $replace = true)
{
$key = str_replace('_', '-', strtolower($key));
$key = strtr($key, self::UPPER, self::LOWER);
if (\is_array($values)) {
$values = array_values($values);
@ -170,7 +171,7 @@ class HeaderBag implements \IteratorAggregate, \Countable
*/
public function has($key)
{
return \array_key_exists(str_replace('_', '-', strtolower($key)), $this->all());
return \array_key_exists(strtr($key, self::UPPER, self::LOWER), $this->all());
}
/**
@ -193,7 +194,7 @@ class HeaderBag implements \IteratorAggregate, \Countable
*/
public function remove($key)
{
$key = str_replace('_', '-', strtolower($key));
$key = strtr($key, self::UPPER, self::LOWER);
unset($this->headers[$key]);

View File

@ -541,7 +541,7 @@ class Request
foreach ($this->headers->all() as $key => $value) {
$key = strtoupper(str_replace('-', '_', $key));
if (\in_array($key, ['CONTENT_TYPE', 'CONTENT_LENGTH'])) {
if (\in_array($key, ['CONTENT_TYPE', 'CONTENT_LENGTH', 'CONTENT_MD5'], true)) {
$_SERVER[$key] = implode(', ', $value);
} else {
$_SERVER['HTTP_'.$key] = implode(', ', $value);

View File

@ -51,7 +51,7 @@ class ResponseHeaderBag extends HeaderBag
{
$headers = [];
foreach ($this->all() as $name => $value) {
$headers[isset($this->headerNames[$name]) ? $this->headerNames[$name] : $name] = $value;
$headers[$this->headerNames[$name] ?? $name] = $value;
}
return $headers;
@ -95,7 +95,7 @@ class ResponseHeaderBag extends HeaderBag
$headers = parent::all();
if (1 <= \func_num_args() && null !== $key = func_get_arg(0)) {
$key = str_replace('_', '-', strtolower($key));
$key = strtr($key, self::UPPER, self::LOWER);
return 'set-cookie' !== $key ? $headers[$key] ?? [] : array_map('strval', $this->getCookies());
}
@ -112,7 +112,7 @@ class ResponseHeaderBag extends HeaderBag
*/
public function set($key, $values, $replace = true)
{
$uniqueKey = str_replace('_', '-', strtolower($key));
$uniqueKey = strtr($key, self::UPPER, self::LOWER);
if ('set-cookie' === $uniqueKey) {
if ($replace) {
@ -143,7 +143,7 @@ class ResponseHeaderBag extends HeaderBag
*/
public function remove($key)
{
$uniqueKey = str_replace('_', '-', strtolower($key));
$uniqueKey = strtr($key, self::UPPER, self::LOWER);
unset($this->headerNames[$uniqueKey]);
if ('set-cookie' === $uniqueKey) {

View File

@ -28,13 +28,10 @@ class ServerBag extends ParameterBag
public function getHeaders()
{
$headers = [];
$contentHeaders = ['CONTENT_LENGTH' => true, 'CONTENT_MD5' => true, 'CONTENT_TYPE' => true];
foreach ($this->parameters as $key => $value) {
if (0 === strpos($key, 'HTTP_')) {
$headers[substr($key, 5)] = $value;
}
// CONTENT_* are not prefixed with HTTP_
elseif (isset($contentHeaders[$key])) {
} elseif (\in_array($key, ['CONTENT_TYPE', 'CONTENT_LENGTH', 'CONTENT_MD5'], true)) {
$headers[$key] = $value;
}
}