fix:更新已知bug,优化代码

This commit is contained in:
Ying
2022-11-28 19:11:12 +08:00
parent f6aee95cfc
commit 9445b206a2
1378 changed files with 53759 additions and 20789 deletions

View File

@@ -48,8 +48,6 @@ class Request
public const HEADER_X_FORWARDED_PORT = 0b010000;
public const HEADER_X_FORWARDED_PREFIX = 0b100000;
/** @deprecated since Symfony 5.2, use either "HEADER_X_FORWARDED_FOR | HEADER_X_FORWARDED_HOST | HEADER_X_FORWARDED_PORT | HEADER_X_FORWARDED_PROTO" or "HEADER_X_FORWARDED_AWS_ELB" or "HEADER_X_FORWARDED_TRAEFIK" constants instead. */
public const HEADER_X_FORWARDED_ALL = 0b1011110; // All "X-Forwarded-*" headers sent by "usual" reverse proxy
public const HEADER_X_FORWARDED_AWS_ELB = 0b0011010; // AWS ELB doesn't send X-Forwarded-Host
public const HEADER_X_FORWARDED_TRAEFIK = 0b0111110; // All "X-Forwarded-*" headers sent by Traefik reverse proxy
@@ -207,19 +205,12 @@ class Request
protected static $requestFactory;
/**
* @var string|null
*/
private $preferredFormat;
private $isHostValid = true;
private $isForwardedValid = true;
private ?string $preferredFormat = null;
private bool $isHostValid = true;
private bool $isForwardedValid = true;
private bool $isSafeContentPreferred;
/**
* @var bool|null
*/
private $isSafeContentPreferred;
private static $trustedHeaderSet = -1;
private static int $trustedHeaderSet = -1;
private const FORWARDED_PARAMS = [
self::HEADER_X_FORWARDED_FOR => 'for',
@@ -298,10 +289,8 @@ class Request
/**
* Creates a new request with values from PHP's super globals.
*
* @return static
*/
public static function createFromGlobals()
public static function createFromGlobals(): static
{
$request = self::createRequestFromFactory($_GET, $_POST, [], $_COOKIE, $_FILES, $_SERVER);
@@ -328,10 +317,8 @@ class Request
* @param array $files The request files ($_FILES)
* @param array $server The server parameters ($_SERVER)
* @param string|resource|null $content The raw body data
*
* @return static
*/
public static function create(string $uri, string $method = 'GET', array $parameters = [], array $cookies = [], array $files = [], array $server = [], $content = null)
public static function create(string $uri, string $method = 'GET', array $parameters = [], array $cookies = [], array $files = [], array $server = [], $content = null): static
{
$server = array_replace([
'SERVER_NAME' => 'localhost',
@@ -445,10 +432,8 @@ class Request
* @param array $cookies The COOKIE parameters
* @param array $files The FILES parameters
* @param array $server The SERVER parameters
*
* @return static
*/
public function duplicate(array $query = null, array $request = null, array $attributes = null, array $cookies = null, array $files = null, array $server = null)
public function duplicate(array $query = null, array $request = null, array $attributes = null, array $cookies = null, array $files = null, array $server = null): static
{
$dup = clone $this;
if (null !== $query) {
@@ -509,12 +494,7 @@ class Request
$this->headers = clone $this->headers;
}
/**
* Returns the request as a string.
*
* @return string
*/
public function __toString()
public function __toString(): string
{
$content = $this->getContent();
@@ -584,9 +564,6 @@ class Request
*/
public static function setTrustedProxies(array $proxies, int $trustedHeaderSet)
{
if (self::HEADER_X_FORWARDED_ALL === $trustedHeaderSet) {
trigger_deprecation('symfony/http-foundation', '5.2', 'The "HEADER_X_FORWARDED_ALL" constant is deprecated, use either "HEADER_X_FORWARDED_FOR | HEADER_X_FORWARDED_HOST | HEADER_X_FORWARDED_PORT | HEADER_X_FORWARDED_PROTO" or "HEADER_X_FORWARDED_AWS_ELB" or "HEADER_X_FORWARDED_TRAEFIK" constants instead.');
}
self::$trustedProxies = array_reduce($proxies, function ($proxies, $proxy) {
if ('REMOTE_ADDR' !== $proxy) {
$proxies[] = $proxy;
@@ -601,10 +578,8 @@ class Request
/**
* Gets the list of trusted proxies.
*
* @return array
*/
public static function getTrustedProxies()
public static function getTrustedProxies(): array
{
return self::$trustedProxies;
}
@@ -614,7 +589,7 @@ class Request
*
* @return int A bit field of Request::HEADER_* that defines which headers are trusted from your proxies
*/
public static function getTrustedHeaderSet()
public static function getTrustedHeaderSet(): int
{
return self::$trustedHeaderSet;
}
@@ -637,10 +612,8 @@ class Request
/**
* Gets the list of trusted host patterns.
*
* @return array
*/
public static function getTrustedHosts()
public static function getTrustedHosts(): array
{
return self::$trustedHostPatterns;
}
@@ -650,10 +623,8 @@ class Request
*
* It builds a normalized query string, where keys/value pairs are alphabetized,
* have consistent escaping and unneeded delimiters are removed.
*
* @return string
*/
public static function normalizeQueryString(?string $qs)
public static function normalizeQueryString(?string $qs): string
{
if ('' === ($qs ?? '')) {
return '';
@@ -683,10 +654,8 @@ class Request
/**
* Checks whether support for the _method request parameter is enabled.
*
* @return bool
*/
public static function getHttpMethodParameterOverride()
public static function getHttpMethodParameterOverride(): bool
{
return self::$httpMethodParameterOverride;
}
@@ -700,13 +669,9 @@ class Request
*
* Order of precedence: PATH (routing placeholders or custom attributes), GET, POST
*
* @param mixed $default The default value if the parameter key does not exist
*
* @return mixed
*
* @internal since Symfony 5.4, use explicit input sources instead
* @internal use explicit input sources instead
*/
public function get(string $key, $default = null)
public function get(string $key, mixed $default = null): mixed
{
if ($this !== $result = $this->attributes->get($key, $this)) {
return $result;
@@ -725,10 +690,8 @@ class Request
/**
* Gets the Session.
*
* @return SessionInterface
*/
public function getSession()
public function getSession(): SessionInterface
{
$session = $this->session;
if (!$session instanceof SessionInterface && null !== $session) {
@@ -745,10 +708,8 @@ class Request
/**
* Whether the request contains a Session which was started in one of the
* previous requests.
*
* @return bool
*/
public function hasPreviousSession()
public function hasPreviousSession(): bool
{
// the check for $this->session avoids malicious users trying to fake a session cookie with proper name
return $this->hasSession() && $this->cookies->has($this->getSession()->getName());
@@ -762,13 +723,9 @@ class Request
* is associated with a Session instance.
*
* @param bool $skipIfUninitialized When true, ignores factories injected by `setSessionFactory`
*
* @return bool
*/
public function hasSession(/* bool $skipIfUninitialized = false */)
public function hasSession(bool $skipIfUninitialized = false): bool
{
$skipIfUninitialized = \func_num_args() > 0 ? func_get_arg(0) : false;
return null !== $this->session && (!$skipIfUninitialized || $this->session instanceof SessionInterface);
}
@@ -796,11 +753,9 @@ class Request
*
* Use this method carefully; you should use getClientIp() instead.
*
* @return array
*
* @see getClientIp()
*/
public function getClientIps()
public function getClientIps(): array
{
$ip = $this->server->get('REMOTE_ADDR');
@@ -824,12 +779,10 @@ class Request
* ("Client-Ip" for instance), configure it via the $trustedHeaderSet
* argument of the Request::setTrustedProxies() method instead.
*
* @return string|null
*
* @see getClientIps()
* @see https://wikipedia.org/wiki/X-Forwarded-For
*/
public function getClientIp()
public function getClientIp(): ?string
{
$ipAddresses = $this->getClientIps();
@@ -838,10 +791,8 @@ class Request
/**
* Returns current script name.
*
* @return string
*/
public function getScriptName()
public function getScriptName(): string
{
return $this->server->get('SCRIPT_NAME', $this->server->get('ORIG_SCRIPT_NAME', ''));
}
@@ -860,7 +811,7 @@ class Request
*
* @return string The raw path (i.e. not urldecoded)
*/
public function getPathInfo()
public function getPathInfo(): string
{
if (null === $this->pathInfo) {
$this->pathInfo = $this->preparePathInfo();
@@ -881,7 +832,7 @@ class Request
*
* @return string The raw path (i.e. not urldecoded)
*/
public function getBasePath()
public function getBasePath(): string
{
if (null === $this->basePath) {
$this->basePath = $this->prepareBasePath();
@@ -900,7 +851,7 @@ class Request
*
* @return string The raw URL (i.e. not urldecoded)
*/
public function getBaseUrl()
public function getBaseUrl(): string
{
$trustedPrefix = '';
@@ -929,10 +880,8 @@ class Request
/**
* Gets the request's scheme.
*
* @return string
*/
public function getScheme()
public function getScheme(): string
{
return $this->isSecure() ? 'https' : 'http';
}
@@ -947,7 +896,7 @@ class Request
*
* @return int|string|null Can be a string if fetched from the server bag
*/
public function getPort()
public function getPort(): int|string|null
{
if ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_X_FORWARDED_PORT)) {
$host = $host[0];
@@ -972,20 +921,16 @@ class Request
/**
* Returns the user.
*
* @return string|null
*/
public function getUser()
public function getUser(): ?string
{
return $this->headers->get('PHP_AUTH_USER');
}
/**
* Returns the password.
*
* @return string|null
*/
public function getPassword()
public function getPassword(): ?string
{
return $this->headers->get('PHP_AUTH_PW');
}
@@ -995,7 +940,7 @@ class Request
*
* @return string|null A user name if any and, optionally, scheme-specific information about how to gain authorization to access the server
*/
public function getUserInfo()
public function getUserInfo(): ?string
{
$userinfo = $this->getUser();
@@ -1011,10 +956,8 @@ class Request
* Returns the HTTP host being requested.
*
* The port name will be appended to the host if it's non-standard.
*
* @return string
*/
public function getHttpHost()
public function getHttpHost(): string
{
$scheme = $this->getScheme();
$port = $this->getPort();
@@ -1031,7 +974,7 @@ class Request
*
* @return string The raw URI (i.e. not URI decoded)
*/
public function getRequestUri()
public function getRequestUri(): string
{
if (null === $this->requestUri) {
$this->requestUri = $this->prepareRequestUri();
@@ -1045,10 +988,8 @@ class Request
*
* If the URL was called with basic authentication, the user
* and the password are not added to the generated string.
*
* @return string
*/
public function getSchemeAndHttpHost()
public function getSchemeAndHttpHost(): string
{
return $this->getScheme().'://'.$this->getHttpHost();
}
@@ -1056,11 +997,9 @@ class Request
/**
* Generates a normalized URI (URL) for the Request.
*
* @return string
*
* @see getQueryString()
*/
public function getUri()
public function getUri(): string
{
if (null !== $qs = $this->getQueryString()) {
$qs = '?'.$qs;
@@ -1073,10 +1012,8 @@ class Request
* Generates a normalized URI for the given path.
*
* @param string $path A path to use instead of the current one
*
* @return string
*/
public function getUriForPath(string $path)
public function getUriForPath(string $path): string
{
return $this->getSchemeAndHttpHost().$this->getBaseUrl().$path;
}
@@ -1095,10 +1032,8 @@ class Request
* - "/a/b/" -> "../"
* - "/a/b/c/other" -> "other"
* - "/a/x/y" -> "../../x/y"
*
* @return string
*/
public function getRelativeUriForPath(string $path)
public function getRelativeUriForPath(string $path): string
{
// be sure that we are dealing with an absolute path
if (!isset($path[0]) || '/' !== $path[0]) {
@@ -1139,10 +1074,8 @@ class Request
*
* It builds a normalized query string, where keys/value pairs are alphabetized
* and have consistent escaping.
*
* @return string|null
*/
public function getQueryString()
public function getQueryString(): ?string
{
$qs = static::normalizeQueryString($this->server->get('QUERY_STRING'));
@@ -1156,10 +1089,8 @@ class Request
* when trusted proxies were set via "setTrustedProxies()".
*
* The "X-Forwarded-Proto" header must contain the protocol: "https" or "http".
*
* @return bool
*/
public function isSecure()
public function isSecure(): bool
{
if ($this->isFromTrustedProxy() && $proto = $this->getTrustedValues(self::HEADER_X_FORWARDED_PROTO)) {
return \in_array(strtolower($proto[0]), ['https', 'on', 'ssl', '1'], true);
@@ -1178,11 +1109,9 @@ class Request
*
* The "X-Forwarded-Host" header must contain the client host name.
*
* @return string
*
* @throws SuspiciousOperationException when the host name is invalid or not trusted
*/
public function getHost()
public function getHost(): string
{
if ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_X_FORWARDED_HOST)) {
$host = $host[0];
@@ -1254,11 +1183,9 @@ class Request
*
* The method is always an uppercased string.
*
* @return string
*
* @see getRealMethod()
*/
public function getMethod()
public function getMethod(): string
{
if (null !== $this->method) {
return $this->method;
@@ -1296,21 +1223,17 @@ class Request
/**
* Gets the "real" request method.
*
* @return string
*
* @see getMethod()
*/
public function getRealMethod()
public function getRealMethod(): string
{
return strtoupper($this->server->get('REQUEST_METHOD', 'GET'));
}
/**
* Gets the mime type associated with the format.
*
* @return string|null
*/
public function getMimeType(string $format)
public function getMimeType(string $format): ?string
{
if (null === static::$formats) {
static::initializeFormats();
@@ -1321,10 +1244,8 @@ class Request
/**
* Gets the mime types associated with the format.
*
* @return array
*/
public static function getMimeTypes(string $format)
public static function getMimeTypes(string $format): array
{
if (null === static::$formats) {
static::initializeFormats();
@@ -1335,10 +1256,8 @@ class Request
/**
* Gets the format associated with the mime type.
*
* @return string|null
*/
public function getFormat(?string $mimeType)
public function getFormat(?string $mimeType): ?string
{
$canonicalMimeType = null;
if ($mimeType && false !== $pos = strpos($mimeType, ';')) {
@@ -1366,7 +1285,7 @@ class Request
*
* @param string|array $mimeTypes The associated mime types (the preferred one must be the first as it will be used as the content type)
*/
public function setFormat(?string $format, $mimeTypes)
public function setFormat(?string $format, string|array $mimeTypes)
{
if (null === static::$formats) {
static::initializeFormats();
@@ -1385,10 +1304,8 @@ class Request
* * $default
*
* @see getPreferredFormat
*
* @return string|null
*/
public function getRequestFormat(?string $default = 'html')
public function getRequestFormat(?string $default = 'html'): ?string
{
if (null === $this->format) {
$this->format = $this->attributes->get('_format');
@@ -1407,10 +1324,8 @@ class Request
/**
* Gets the format associated with the request.
*
* @return string|null
*/
public function getContentType()
public function getContentType(): ?string
{
return $this->getFormat($this->headers->get('CONTENT_TYPE', ''));
}
@@ -1429,10 +1344,8 @@ class Request
/**
* Get the default locale.
*
* @return string
*/
public function getDefaultLocale()
public function getDefaultLocale(): string
{
return $this->defaultLocale;
}
@@ -1447,10 +1360,8 @@ class Request
/**
* Get the locale.
*
* @return string
*/
public function getLocale()
public function getLocale(): string
{
return null === $this->locale ? $this->defaultLocale : $this->locale;
}
@@ -1459,10 +1370,8 @@ class Request
* Checks if the request method is of specified type.
*
* @param string $method Uppercase request method (GET, POST etc)
*
* @return bool
*/
public function isMethod(string $method)
public function isMethod(string $method): bool
{
return $this->getMethod() === strtoupper($method);
}
@@ -1471,20 +1380,16 @@ class Request
* Checks whether or not the method is safe.
*
* @see https://tools.ietf.org/html/rfc7231#section-4.2.1
*
* @return bool
*/
public function isMethodSafe()
public function isMethodSafe(): bool
{
return \in_array($this->getMethod(), ['GET', 'HEAD', 'OPTIONS', 'TRACE']);
}
/**
* Checks whether or not the method is idempotent.
*
* @return bool
*/
public function isMethodIdempotent()
public function isMethodIdempotent(): bool
{
return \in_array($this->getMethod(), ['HEAD', 'GET', 'PUT', 'DELETE', 'TRACE', 'OPTIONS', 'PURGE']);
}
@@ -1493,10 +1398,8 @@ class Request
* Checks whether the method is cacheable or not.
*
* @see https://tools.ietf.org/html/rfc7231#section-4.2.3
*
* @return bool
*/
public function isMethodCacheable()
public function isMethodCacheable(): bool
{
return \in_array($this->getMethod(), ['GET', 'HEAD']);
}
@@ -1509,10 +1412,8 @@ class Request
* server might be different. This returns the former (from the "Via" header)
* if the proxy is trusted (see "setTrustedProxies()"), otherwise it returns
* the latter (from the "SERVER_PROTOCOL" server parameter).
*
* @return string|null
*/
public function getProtocolVersion()
public function getProtocolVersion(): ?string
{
if ($this->isFromTrustedProxy()) {
preg_match('~^(HTTP/)?([1-9]\.[0-9]) ~', $this->headers->get('Via') ?? '', $matches);
@@ -1574,25 +1475,19 @@ class Request
* Gets the request body decoded as array, typically from a JSON payload.
*
* @throws JsonException When the body cannot be decoded to an array
*
* @return array
*/
public function toArray()
public function toArray(): array
{
if ('' === $content = $this->getContent()) {
throw new JsonException('Request body is empty.');
}
try {
$content = json_decode($content, true, 512, \JSON_BIGINT_AS_STRING | (\PHP_VERSION_ID >= 70300 ? \JSON_THROW_ON_ERROR : 0));
$content = json_decode($content, true, 512, \JSON_BIGINT_AS_STRING | \JSON_THROW_ON_ERROR);
} catch (\JsonException $e) {
throw new JsonException('Could not decode request body.', $e->getCode(), $e);
}
if (\PHP_VERSION_ID < 70300 && \JSON_ERROR_NONE !== json_last_error()) {
throw new JsonException('Could not decode request body: '.json_last_error_msg(), json_last_error());
}
if (!\is_array($content)) {
throw new JsonException(sprintf('JSON content was expected to decode to an array, "%s" returned.', get_debug_type($content)));
}
@@ -1602,18 +1497,13 @@ class Request
/**
* Gets the Etags.
*
* @return array
*/
public function getETags()
public function getETags(): array
{
return preg_split('/\s*,\s*/', $this->headers->get('If-None-Match', ''), -1, \PREG_SPLIT_NO_EMPTY);
}
/**
* @return bool
*/
public function isNoCache()
public function isNoCache(): bool
{
return $this->headers->hasCacheControlDirective('no-cache') || 'no-cache' == $this->headers->get('Pragma');
}
@@ -1645,10 +1535,8 @@ class Request
* Returns the preferred language.
*
* @param string[] $locales An array of ordered available locales
*
* @return string|null
*/
public function getPreferredLanguage(array $locales = null)
public function getPreferredLanguage(array $locales = null): ?string
{
$preferredLanguages = $this->getLanguages();
@@ -1678,10 +1566,8 @@ class Request
/**
* Gets a list of languages acceptable by the client browser ordered in the user browser preferences.
*
* @return array
*/
public function getLanguages()
public function getLanguages(): array
{
if (null !== $this->languages) {
return $this->languages;
@@ -1689,7 +1575,8 @@ class Request
$languages = AcceptHeader::fromString($this->headers->get('Accept-Language'))->all();
$this->languages = [];
foreach ($languages as $lang => $acceptHeaderItem) {
foreach ($languages as $acceptHeaderItem) {
$lang = $acceptHeaderItem->getValue();
if (str_contains($lang, '-')) {
$codes = explode('-', $lang);
if ('i' === $codes[0]) {
@@ -1718,44 +1605,38 @@ class Request
/**
* Gets a list of charsets acceptable by the client browser in preferable order.
*
* @return array
*/
public function getCharsets()
public function getCharsets(): array
{
if (null !== $this->charsets) {
return $this->charsets;
}
return $this->charsets = array_keys(AcceptHeader::fromString($this->headers->get('Accept-Charset'))->all());
return $this->charsets = array_map('strval', array_keys(AcceptHeader::fromString($this->headers->get('Accept-Charset'))->all()));
}
/**
* Gets a list of encodings acceptable by the client browser in preferable order.
*
* @return array
*/
public function getEncodings()
public function getEncodings(): array
{
if (null !== $this->encodings) {
return $this->encodings;
}
return $this->encodings = array_keys(AcceptHeader::fromString($this->headers->get('Accept-Encoding'))->all());
return $this->encodings = array_map('strval', array_keys(AcceptHeader::fromString($this->headers->get('Accept-Encoding'))->all()));
}
/**
* Gets a list of content types acceptable by the client browser in preferable order.
*
* @return array
*/
public function getAcceptableContentTypes()
public function getAcceptableContentTypes(): array
{
if (null !== $this->acceptableContentTypes) {
return $this->acceptableContentTypes;
}
return $this->acceptableContentTypes = array_keys(AcceptHeader::fromString($this->headers->get('Accept'))->all());
return $this->acceptableContentTypes = array_map('strval', array_keys(AcceptHeader::fromString($this->headers->get('Accept'))->all()));
}
/**
@@ -1765,10 +1646,8 @@ class Request
* It is known to work with common JavaScript frameworks:
*
* @see https://wikipedia.org/wiki/List_of_Ajax_frameworks#JavaScript
*
* @return bool
*/
public function isXmlHttpRequest()
public function isXmlHttpRequest(): bool
{
return 'XMLHttpRequest' == $this->headers->get('X-Requested-With');
}
@@ -1780,7 +1659,7 @@ class Request
*/
public function preferSafeContent(): bool
{
if (null !== $this->isSafeContentPreferred) {
if (isset($this->isSafeContentPreferred)) {
return $this->isSafeContentPreferred;
}
@@ -1847,10 +1726,8 @@ class Request
/**
* Prepares the base URL.
*
* @return string
*/
protected function prepareBaseUrl()
protected function prepareBaseUrl(): string
{
$filename = basename($this->server->get('SCRIPT_FILENAME', ''));
@@ -1916,10 +1793,8 @@ class Request
/**
* Prepares the base path.
*
* @return string
*/
protected function prepareBasePath()
protected function prepareBasePath(): string
{
$baseUrl = $this->getBaseUrl();
if (empty($baseUrl)) {
@@ -1942,10 +1817,8 @@ class Request
/**
* Prepares the path info.
*
* @return string
*/
protected function preparePathInfo()
protected function preparePathInfo(): string
{
if (null === ($requestUri = $this->getRequestUri())) {
return '/';
@@ -2024,7 +1897,7 @@ class Request
return null;
}
private static function createRequestFromFactory(array $query = [], array $request = [], array $attributes = [], array $cookies = [], array $files = [], array $server = [], $content = null): self
private static function createRequestFromFactory(array $query = [], array $request = [], array $attributes = [], array $cookies = [], array $files = [], array $server = [], $content = null): static
{
if (self::$requestFactory) {
$request = (self::$requestFactory)($query, $request, $attributes, $cookies, $files, $server, $content);
@@ -2044,10 +1917,8 @@ class Request
*
* This can be useful to determine whether or not to trust the
* contents of a proxy-specific header.
*
* @return bool
*/
public function isFromTrustedProxy()
public function isFromTrustedProxy(): bool
{
return self::$trustedProxies && IpUtils::checkIp($this->server->get('REMOTE_ADDR', ''), self::$trustedProxies);
}