# Request

class Request

Request represents an HTTP request.

The methods dealing with URL accept / return a raw path (% encoded): * getBasePath * getBaseUrl * getPathInfo * getRequestUri * getUri * getUriForPath

## Constants

`HEADER_FORWARDED = 0b00001; // When using RFC 7239` |
`HEADER_X_FORWARDED_FOR = 0b00010;` |
`HEADER_X_FORWARDED_HOST = 0b00100;` |
`HEADER_X_FORWARDED_PROTO = 0b01000;` |
`HEADER_X_FORWARDED_PORT = 0b10000;` |
`HEADER_X_FORWARDED_ALL = 0b11110; // All "X-Forwarded-*" headers` |
`HEADER_X_FORWARDED_AWS_ELB = 0b11010; // AWS ELB doesn't send X-Forwarded-Host` |
`METHOD_HEAD = 'HEAD';` |
`METHOD_GET = 'GET';` |
`METHOD_POST = 'POST';` |
`METHOD_PUT = 'PUT';` |
`METHOD_PATCH = 'PATCH';` |
`METHOD_DELETE = 'DELETE';` |
`METHOD_PURGE = 'PURGE';` |
`METHOD_OPTIONS = 'OPTIONS';` |
`METHOD_TRACE = 'TRACE';` |
`METHOD_CONNECT = 'CONNECT';` |

## Properties

`static protected string[]` | `$trustedProxies` |  |
`static protected string[]` | `$trustedHostPatterns` |  |
`static protected string[]` | `$trustedHosts` |  |
`static protected` | `$httpMethodParameterOverride` |  |
`ParameterBag` | `$attributes` | Custom parameters. |
`ParameterBag` | `$request` | Request body parameters ($_POST). |
`ParameterBag` | `$query` | Query string parameters ($_GET). |
`ServerBag` | `$server` | Server and execution environment parameters ($_SERVER). |
`FileBag` | `$files` | Uploaded files ($_FILES). |
`ParameterBag` | `$cookies` | Cookies ($_COOKIE). |
`HeaderBag` | `$headers` | Headers (taken from the $_SERVER). |
`protected string|resource|false|null` | `$content` |  |
`protected array` | `$languages` |  |
`protected array` | `$charsets` |  |
`protected array` | `$encodings` |  |
`protected array` | `$acceptableContentTypes` |  |
`protected string` | `$pathInfo` |  |
`protected string` | `$requestUri` |  |
`protected string` | `$baseUrl` |  |
`protected string` | `$basePath` |  |
`protected string` | `$method` |  |
`protected string` | `$format` |  |
`protected SessionInterface` | `$session` |  |
`protected string` | `$locale` |  |
`protected string` | `$defaultLocale` |  |
`static protected array` | `$formats` |  |
`static protected` | `$requestFactory` |  |

## Methods

`public` | `` | `__construct(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), string|resource|null $content = null)` | No description |
`public` | `` | `initialize(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), string|resource|null $content = null)` | Sets the parameters for this request. |
`public static` | `Request` | `createFromGlobals()` | Creates a new request with values from PHP's super globals. |
`public static` | `Request` | `create(string $uri, string $method = 'GET', array $parameters = array(), array $cookies = array(), array $files = array(), array $server = array(), string|resource|null $content = null)` | Creates a Request based on a given URI and configuration. |
`public static` | `` | `setFactory(callable|null $callable)` | Sets a callable able to create a Request instance. |
`public` | `Request` | `duplicate(array $query = null, array $request = null, array $attributes = null, array $cookies = null, array $files = null, array $server = null)` | Clones a request and overrides some of its parameters. |
`public` | `` | `__clone()` | Clones the current request. |
`public` | `string` | `__toString()` | Returns the request as a string. |
`public` | `` | `overrideGlobals()` | Overrides the PHP global variables according to this request instance. |
`public static` | `` | `setTrustedProxies(array $proxies, int $trustedHeaderSet)` | Sets a list of trusted proxies. |
`public static` | `array` | `getTrustedProxies()` | Gets the list of trusted proxies. |
`public static` | `int` | `getTrustedHeaderSet()` | Gets the set of trusted headers from trusted proxies. |
`public static` | `` | `setTrustedHosts(array $hostPatterns)` | Sets a list of trusted host patterns. |
`public static` | `array` | `getTrustedHosts()` | Gets the list of trusted host patterns. |
`public static` | `string` | `normalizeQueryString(string $qs)` | Normalizes a query string. |
`public static` | `` | `enableHttpMethodParameterOverride()` | Enables support for the _method request parameter to determine the intended HTTP method. |
`public static` | `bool` | `getHttpMethodParameterOverride()` | Checks whether support for the _method request parameter is enabled. |
`public` | `mixed` | `get(string $key, mixed $default = null)` | Gets a "parameter" value from any bag. |
`public` | `SessionInterface|null` | `getSession()` | Gets the Session. |
`public` | `bool` | `hasPreviousSession()` | Whether the request contains a Session which was started in one of the previous requests. |
`public` | `bool` | `hasSession()` | Whether the request contains a Session object. |
`public` | `` | `setSession(SessionInterface $session)` | Sets the Session. |
`public` | `` | `setSessionFactory(callable $factory)` | No description |
`public` | `array` | `getClientIps()` | Returns the client IP addresses. |
`public` | `string|null` | `getClientIp()` | Returns the client IP address. |
`public` | `string` | `getScriptName()` | Returns current script name. |
`public` | `string` | `getPathInfo()` | Returns the path being requested relative to the executed script. |
`public` | `string` | `getBasePath()` | Returns the root path from which this request is executed. |
`public` | `string` | `getBaseUrl()` | Returns the root URL from which this request is executed. |
`public` | `string` | `getScheme()` | Gets the request's scheme. |
`public` | `int|string` | `getPort()` | Returns the port on which the request is made. |
`public` | `string|null` | `getUser()` | Returns the user. |
`public` | `string|null` | `getPassword()` | Returns the password. |
`public` | `string` | `getUserInfo()` | Gets the user info. |
`public` | `string` | `getHttpHost()` | Returns the HTTP host being requested. |
`public` | `string` | `getRequestUri()` | Returns the requested URI (path and query string). |
`public` | `string` | `getSchemeAndHttpHost()` | Gets the scheme and HTTP host. |
`public` | `string` | `getUri()` | Generates a normalized URI (URL) for the Request. |
`public` | `string` | `getUriForPath(string $path)` | Generates a normalized URI for the given path. |
`public` | `string` | `getRelativeUriForPath(string $path)` | Returns the path as relative reference from the current Request path. |
`public` | `string|null` | `getQueryString()` | Generates the normalized query string for the Request. |
`public` | `bool` | `isSecure()` | Checks whether the request is secure or not. |
`public` | `string` | `getHost()` | Returns the host name. |
`public` | `` | `setMethod(string $method)` | Sets the request method. |
`public` | `string` | `getMethod()` | Gets the request "intended" method. |
`public` | `string` | `getRealMethod()` | Gets the "real" request method. |
`public` | `string` | `getMimeType(string $format)` | Gets the mime type associated with the format. |
`public static` | `array` | `getMimeTypes(string $format)` | Gets the mime types associated with the format. |
`public` | `string|null` | `getFormat(string $mimeType)` | Gets the format associated with the mime type. |
`public` | `` | `setFormat(string $format, string|array $mimeTypes)` | Associates a format with mime types. |
`public` | `string` | `getRequestFormat(string $default = 'html')` | Gets the request format. |
`public` | `` | `setRequestFormat(string $format)` | Sets the request format. |
`public` | `string|null` | `getContentType()` | Gets the format associated with the request. |
`public` | `` | `setDefaultLocale(string $locale)` | Sets the default locale. |
`public` | `string` | `getDefaultLocale()` | Get the default locale. |
`public` | `` | `setLocale(string $locale)` | Sets the locale. |
`public` | `string` | `getLocale()` | Get the locale. |
`public` | `bool` | `isMethod(string $method)` | Checks if the request method is of specified type. |
`public` | `bool` | `isMethodSafe()` | Checks whether or not the method is safe. |
`public` | `bool` | `isMethodIdempotent()` | Checks whether or not the method is idempotent. |
`public` | `bool` | `isMethodCacheable()` | Checks whether the method is cacheable or not. |
`public` | `string` | `getProtocolVersion()` | Returns the protocol version. |
`public` | `string|resource` | `getContent(bool $asResource = false)` | Returns the request body content. |
`public` | `array` | `getETags()` | Gets the Etags. |
`public` | `bool` | `isNoCache()` | No description |
`public` | `string|null` | `getPreferredLanguage(array $locales = null)` | Returns the preferred language. |
`public` | `array` | `getLanguages()` | Gets a list of languages acceptable by the client browser. |
`public` | `array` | `getCharsets()` | Gets a list of charsets acceptable by the client browser. |
`public` | `array` | `getEncodings()` | Gets a list of encodings acceptable by the client browser. |
`public` | `array` | `getAcceptableContentTypes()` | Gets a list of content types acceptable by the client browser. |
`public` | `bool` | `isXmlHttpRequest()` | Returns true if the request is a XMLHttpRequest. |
`protected` | `` | `prepareRequestUri()` | No description |
`protected` | `string` | `prepareBaseUrl()` | Prepares the base URL. |
`protected` | `string` | `prepareBasePath()` | Prepares the base path. |
`protected` | `string` | `preparePathInfo()` | Prepares the path info. |
`protected static` | `` | `initializeFormats()` | Initializes HTTP request formats. |
`public` | `bool` | `isFromTrustedProxy()` | Indicates whether this request originated from a trusted proxy. |

## Details

at line 233

### `__construct()`

`public __construct(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), string|resource|null $content = null)`

#### Parameters

`array` | `$query` | The GET parameters
`array` | `$request` | The POST parameters
`array` | `$attributes` | The request attributes (parameters parsed from the PATH_INFO, ...)
`array` | `$cookies` | The COOKIE parameters
`array` | `$files` | The FILES parameters
`array` | `$server` | The SERVER parameters
`string|resource|null` | `$content` | The raw body data

at line 251

### `initialize()`

`public initialize(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), string|resource|null $content = null)`

Sets the parameters for this request.

This method also re-initializes all properties.

#### Parameters

`array` | `$query` | The GET parameters
`array` | `$request` | The POST parameters
`array` | `$attributes` | The request attributes (parameters parsed from the PATH_INFO, ...)
`array` | `$cookies` | The COOKIE parameters
`array` | `$files` | The FILES parameters
`array` | `$server` | The SERVER parameters
`string|resource|null` | `$content` | The raw body data

at line 279

### `createFromGlobals()`

`public static Request createFromGlobals()`

Creates a new request with values from PHP's super globals.

#### Return Value

`Request` |

at line 309

### `create()`

`public static Request create(string $uri, string $method = 'GET', array $parameters = array(), array $cookies = array(), array $files = array(), array $server = array(), string|resource|null $content = null)`

Creates a Request based on a given URI and configuration.

The information contained in the URI always take precedence over the other information (server and parameters).

#### Parameters

`string` | `$uri` | The URI
`string` | `$method` | The HTTP method
`array` | `$parameters` | The query (GET) or request (POST) parameters
`array` | `$cookies` | The request cookies ($_COOKIE)
`array` | `$files` | The request files ($_FILES)
`array` | `$server` | The server parameters ($_SERVER)
`string|resource|null` | `$content` | The raw body data

#### Return Value

`Request` |

at line 410

### `setFactory()`

`public static setFactory(callable|null $callable)`

Sets a callable able to create a Request instance.

This is mainly useful when you need to override the Request class to keep BC with an existing system. It should not be used for any other purpose.

#### Parameters

`callable|null` | `$callable` | A PHP callable

at line 427

### `duplicate()`

`public Request duplicate(array $query = null, array $request = null, array $attributes = null, array $cookies = null, array $files = null, array $server = null)`

Clones a request and overrides some of its parameters.

#### Parameters

`array` | `$query` | The GET parameters
`array` | `$request` | The POST parameters
`array` | `$attributes` | The request attributes (parameters parsed from the PATH_INFO, ...)
`array` | `$cookies` | The COOKIE parameters
`array` | `$files` | The FILES parameters
`array` | `$server` | The SERVER parameters

#### Return Value

`Request` |

at line 477

### `__clone()`

`public __clone()`

Clones the current request.

Note that the session is not cloned as duplicated requests are most of the time sub-requests of the main one.

at line 493

### `__toString()`

`public string __toString()`

Returns the request as a string.

#### Return Value

`string` | The request

at line 525

### `overrideGlobals()`

`public overrideGlobals()`

Overrides the PHP global variables according to this request instance.

It overrides $_GET, $_POST, $_REQUEST, $_SERVER, $_COOKIE. $_FILES is never overridden, see rfc1867

at line 564

### `setTrustedProxies()`

`public static setTrustedProxies(array $proxies, int $trustedHeaderSet)`

Sets a list of trusted proxies.

You should only list the reverse proxies that you manage directly.

#### Parameters

`array` | `$proxies` | A list of trusted proxies
`int` | `$trustedHeaderSet` | A bit field of Request::HEADER_*, to set which headers to trust from your proxies

#### Exceptions

InvalidArgumentException | When $trustedHeaderSet is invalid

at line 575

### `getTrustedProxies()`

`public static array getTrustedProxies()`

Gets the list of trusted proxies.

#### Return Value

`array` | An array of trusted proxies

at line 585

### `getTrustedHeaderSet()`

`public static int getTrustedHeaderSet()`

Gets the set of trusted headers from trusted proxies.

#### Return Value

`int` | A bit field of Request::HEADER_* that defines which headers are trusted from your proxies

at line 597

### `setTrustedHosts()`

`public static setTrustedHosts(array $hostPatterns)`

Sets a list of trusted host patterns.

You should only list the hosts you manage using regexs.

#### Parameters

`array` | `$hostPatterns` | A list of trusted host patterns

at line 611

### `getTrustedHosts()`

`public static array getTrustedHosts()`

Gets the list of trusted host patterns.

#### Return Value

`array` | An array of trusted host patterns

at line 626

### `normalizeQueryString()`

`public static string normalizeQueryString(string $qs)`

Normalizes a query string.

It builds a normalized query string, where keys/value pairs are alphabetized, have consistent escaping and unneeded delimiters are removed.

#### Parameters

`string` | `$qs` | Query string

#### Return Value

`string` | A normalized query string for the Request

at line 649

### `enableHttpMethodParameterOverride()`

`public static enableHttpMethodParameterOverride()`

Enables support for the _method request parameter to determine the intended HTTP method.

Be warned that enabling this feature might lead to CSRF issues in your code. Check that you are using CSRF tokens when required. If the HTTP method parameter override is enabled, an html-form with method "POST" can be altered and used to send a "PUT" or "DELETE" request via the _method request parameter. If these methods are not protected against CSRF, this presents a possible vulnerability.

The HTTP method can only be overridden when the real HTTP method is POST.

at line 659

### `getHttpMethodParameterOverride()`

`public static bool getHttpMethodParameterOverride()`

Checks whether support for the _method request parameter is enabled.

#### Return Value

`bool` | True when the _method request parameter is enabled, false otherwise

at line 678

### `get()`

`public mixed get(string $key, mixed $default = null)`

Gets a "parameter" value from any bag.

This method is mainly useful for libraries that want to provide some flexibility. If you don't need the flexibility in controllers, it is better to explicitly get request parameters from the appropriate public property instead (attributes, query, request).

Order of precedence: PATH (routing placeholders or custom attributes), GET, BODY

#### Parameters

`string` | `$key` | The key
`mixed` | `$default` | The default value if the parameter key does not exist

#### Return Value

`mixed` |

at line 700

### `getSession()`

`public SessionInterface|null getSession()`

Gets the Session.

#### Return Value

`SessionInterface|null` | The session

at line 721

### `hasPreviousSession()`

`public bool hasPreviousSession()`

Whether the request contains a Session which was started in one of the previous requests.

#### Return Value

`bool` |

at line 736

### `hasSession()`

`public bool hasSession()`

Whether the request contains a Session object.

This method does not give any information about the state of the session object, like whether the session is started or not. It is just a way to check if this Request is associated with a Session instance.

#### Return Value

`bool` | true when the Request contains a Session object, false otherwise

at line 746

### `setSession()`

`public setSession(SessionInterface $session)`

Sets the Session.

#### Parameters

`SessionInterface` | `$session` | The Session

at line 754

### `setSessionFactory()`

`public setSessionFactory(callable $factory)`

#### Parameters

`callable` | `$factory` |

at line 772

### `getClientIps()`

`public array getClientIps()`

Returns the client IP addresses.

In the returned array the most trusted IP address is first, and the least trusted one last. The "real" client IP address is the last one, but this is also the least trusted one. Trusted proxies are stripped.

Use this method carefully; you should use getClientIp() instead.

#### Return Value

`array` | The client IP addresses

#### See also

getClientIp() |

at line 797

### `getClientIp()`

`public string|null getClientIp()`

Returns the client IP address.

This method can read the client IP address from the "X-Forwarded-For" header when trusted proxies were set via "setTrustedProxies()". The "X-Forwarded-For" header value is a comma+space separated list of IP addresses, the left-most being the original client, and each successive proxy that passed the request adding the IP address where it received the request from.

#### Return Value

`string|null` | The client IP address

#### See also

getClientIps() |
http://en.wikipedia.org/wiki/X-Forwarded-For |

at line 809

### `getScriptName()`

`public string getScriptName()`

Returns current script name.

#### Return Value

`string` |

at line 828

### `getPathInfo()`

`public string getPathInfo()`

Returns the path being requested relative to the executed script.

The path info always starts with a /.

Suppose this request is instantiated from /mysite on localhost:

- http://localhost/mysite returns an empty string
- http://localhost/mysite/about returns '/about'
- http://localhost/mysite/enco%20ded returns '/enco%20ded'
- http://localhost/mysite/about?var=1 returns '/about'

#### Return Value

`string` | The raw path (i.e. not urldecoded)

at line 849

### `getBasePath()`

`public string getBasePath()`

Returns the root path from which this request is executed.

Suppose that an index.php file instantiates this request object:

- http://localhost/index.php returns an empty string
- http://localhost/index.php/page returns an empty string
- http://localhost/web/index.php returns '/web'
- http://localhost/we%20b/index.php returns '/we%20b'

#### Return Value

`string` | The raw path (i.e. not urldecoded)

at line 868

### `getBaseUrl()`

`public string getBaseUrl()`

Returns the root URL from which this request is executed.

The base URL never ends with a /.

This is similar to getBasePath(), except that it also includes the script filename (e.g. index.php) if one exists.

#### Return Value

`string` | The raw URL (i.e. not urldecoded)

at line 882

### `getScheme()`

`public string getScheme()`

Gets the request's scheme.

#### Return Value

`string` |

at line 897

### `getPort()`

`public int|string getPort()`

Returns the port on which the request is made.

This method can read the client port from the "X-Forwarded-Port" header when trusted proxies were set via "setTrustedProxies()".

The "X-Forwarded-Port" header must contain the client port.

#### Return Value

`int|string` | can be a string if fetched from the server bag

at line 925

### `getUser()`

`public string|null getUser()`

Returns the user.

#### Return Value

`string|null` |

at line 935

### `getPassword()`

`public string|null getPassword()`

Returns the password.

#### Return Value

`string|null` |

at line 945

### `getUserInfo()`

`public string getUserInfo()`

Gets the user info.

#### Return Value

`string` | A user name and, optionally, scheme-specific information about how to gain authorization to access the server

at line 964

### `getHttpHost()`

`public string getHttpHost()`

Returns the HTTP host being requested.

The port name will be appended to the host if it's non-standard.

#### Return Value

`string` |

at line 981

### `getRequestUri()`

`public string getRequestUri()`

Returns the requested URI (path and query string).

#### Return Value

`string` | The raw URI (i.e. not URI decoded)

at line 998

### `getSchemeAndHttpHost()`

`public string getSchemeAndHttpHost()`

Gets the scheme and HTTP host.

If the URL was called with basic authentication, the user and the password are not added to the generated string.

#### Return Value

`string` | The scheme and HTTP host

at line 1010

### `getUri()`

`public string getUri()`

Generates a normalized URI (URL) for the Request.

#### Return Value

`string` | A normalized URI (URL) for the Request

#### See also

getQueryString() |

at line 1026

### `getUriForPath()`

`public string getUriForPath(string $path)`

Generates a normalized URI for the given path.

#### Parameters

`string` | `$path` | A path to use instead of the current one

#### Return Value

`string` | The normalized URI for the path

at line 1050

### `getRelativeUriForPath()`

`public string getRelativeUriForPath(string $path)`

Returns the path as relative reference from the current Request path.

Only the URIs path component (no schema, host etc.) is relevant and must be given. Both paths must be absolute and not contain relative parts. Relative URLs from one resource to another are useful when generating self-contained downloadable document archives. Furthermore, they can be used to reduce the link size in documents.

Example target paths, given a base path of "/a/b/c/d": - "/a/b/c/d" -> "" - "/a/b/c/" -> "./" - "/a/b/" -> "../" - "/a/b/c/other" -> "other" - "/a/x/y" -> "../../x/y"

#### Parameters

`string` | `$path` | The target path

#### Return Value

`string` | The relative target path

at line 1094

### `getQueryString()`

`public string|null getQueryString()`

Generates the normalized query string for the Request.

It builds a normalized query string, where keys/value pairs are alphabetized and have consistent escaping.

#### Return Value

`string|null` | A normalized query string for the Request

at line 1111

### `isSecure()`

`public bool isSecure()`

Checks whether the request is secure or not.

This method can read the client protocol from the "X-Forwarded-Proto" header when trusted proxies were set via "setTrustedProxies()".

The "X-Forwarded-Proto" header must contain the protocol: "https" or "http".

#### Return Value

`bool` |

at line 1134

### `getHost()`

`public string getHost()`

Returns the host name.

This method can read the client host name from the "X-Forwarded-Host" header when trusted proxies were set via "setTrustedProxies()".

The "X-Forwarded-Host" header must contain the client host name.

#### Return Value

`string` |

#### Exceptions

SuspiciousOperationException | when the host name is invalid or not trusted

at line 1191

### `setMethod()`

`public setMethod(string $method)`

Sets the request method.

#### Parameters

`string` | `$method` |

at line 1212

### `getMethod()`

`public string getMethod()`

Gets the request "intended" method.

If the X-HTTP-Method-Override header is set, and if the method is a POST, then it is used to determine the "real" intended HTTP method.

The _method request parameter can also be used to determine the HTTP method, but only if enableHttpMethodParameterOverride() has been called.

The method is always an uppercased string.

#### Return Value

`string` | The request method

#### See also

getRealMethod() |

at line 1236

### `getRealMethod()`

`public string getRealMethod()`

Gets the "real" request method.

#### Return Value

`string` | The request method

#### See also

getMethod() |

at line 1248

### `getMimeType()`

`public string getMimeType(string $format)`

Gets the mime type associated with the format.

#### Parameters

`string` | `$format` | The format

#### Return Value

`string` | The associated mime type (null if not found)

at line 1264

### `getMimeTypes()`

`public static array getMimeTypes(string $format)`

Gets the mime types associated with the format.

#### Parameters

`string` | `$format` | The format

#### Return Value

`array` | The associated mime types

at line 1280

### `getFormat()`

`public string|null getFormat(string $mimeType)`

Gets the format associated with the mime type.

#### Parameters

`string` | `$mimeType` | The associated mime type

#### Return Value

`string|null` | The format (null if not found)

at line 1307

### `setFormat()`

`public setFormat(string $format, string|array $mimeTypes)`

Associates a format with mime types.

#### Parameters

`string` | `$format` | The format
`string|array` | `$mimeTypes` | The associated mime types (the preferred one must be the first as it will be used as the content type)

at line 1329

### `getRequestFormat()`

`public string getRequestFormat(string $default = 'html')`

Gets the request format.

Here is the process to determine the format:

- format defined by the user (with setRequestFormat())
- _format request attribute
- $default

#### Parameters

`string` | `$default` | The default format

#### Return Value

`string` | The request format

at line 1343

### `setRequestFormat()`

`public setRequestFormat(string $format)`

Sets the request format.

#### Parameters

`string` | `$format` | The request format

at line 1353

### `getContentType()`

`public string|null getContentType()`

Gets the format associated with the request.

#### Return Value

`string|null` | The format (null if no content type is present)

at line 1363

### `setDefaultLocale()`

`public setDefaultLocale(string $locale)`

Sets the default locale.

#### Parameters

`string` | `$locale` |

at line 1377

### `getDefaultLocale()`

`public string getDefaultLocale()`

Get the default locale.

#### Return Value

`string` |

at line 1387

### `setLocale()`

`public setLocale(string $locale)`

Sets the locale.

#### Parameters

`string` | `$locale` |

at line 1397

### `getLocale()`

`public string getLocale()`

Get the locale.

#### Return Value

`string` |

at line 1409

### `isMethod()`

`public bool isMethod(string $method)`

Checks if the request method is of specified type.

#### Parameters

`string` | `$method` | Uppercase request method (GET, POST etc)

#### Return Value

`bool` |

at line 1423

### `isMethodSafe()`

`public bool isMethodSafe()`

Checks whether or not the method is safe.

#### Return Value

`bool` |

#### See also

https://tools.ietf.org/html/rfc7231#section-4.2.1 |

at line 1438

### `isMethodIdempotent()`

`public bool isMethodIdempotent()`

Checks whether or not the method is idempotent.

#### Return Value

`bool` |

at line 1450

### `isMethodCacheable()`

`public bool isMethodCacheable()`

Checks whether the method is cacheable or not.

#### Return Value

`bool` |

#### See also

https://tools.ietf.org/html/rfc7231#section-4.2.3 |

at line 1466

### `getProtocolVersion()`

`public string getProtocolVersion()`

Returns the protocol version.

If the application is behind a proxy, the protocol version used in the requests between the client and the proxy and between the proxy and the 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 Value

`string` |

at line 1488

### `getContent()`

`public string|resource getContent(bool $asResource = false)`

Returns the request body content.

#### Parameters

`bool` | `$asResource` | If true, a resource will be returned

#### Return Value

`string|resource` | The request body content or a resource to read the body stream

#### Exceptions

LogicException |

at line 1531

### `getETags()`

`public array getETags()`

Gets the Etags.

#### Return Value

`array` | The entity tags

at line 1539

### `isNoCache()`

`public bool isNoCache()`

#### Return Value

`bool` |

at line 1551

### `getPreferredLanguage()`

`public string|null getPreferredLanguage(array $locales = null)`

Returns the preferred language.

#### Parameters

`array` | `$locales` | An array of ordered available locales

#### Return Value

`string|null` | The preferred locale

at line 1584

### `getLanguages()`

`public array getLanguages()`

Gets a list of languages acceptable by the client browser.

#### Return Value

`array` | Languages ordered in the user browser preferences

at line 1624

### `getCharsets()`

`public array getCharsets()`

Gets a list of charsets acceptable by the client browser.

#### Return Value

`array` | List of charsets in preferable order

at line 1638

### `getEncodings()`

`public array getEncodings()`

Gets a list of encodings acceptable by the client browser.

#### Return Value

`array` | List of encodings in preferable order

at line 1652

### `getAcceptableContentTypes()`

`public array getAcceptableContentTypes()`

Gets a list of content types acceptable by the client browser.

#### Return Value

`array` | List of content types in preferable order

at line 1671

### `isXmlHttpRequest()`

`public bool isXmlHttpRequest()`

Returns true if the request is a XMLHttpRequest.

It works if your JavaScript library sets an X-Requested-With HTTP header. It is known to work with common JavaScript frameworks:

#### Return Value

`bool` | true if the request is an XMLHttpRequest, false otherwise

#### See also

http://en.wikipedia.org/wiki/List_of_Ajax_frameworks#JavaScript |

at line 1684

### `prepareRequestUri()`

`protected prepareRequestUri()`
at line 1731

### `prepareBaseUrl()`

`protected string prepareBaseUrl()`

Prepares the base URL.

#### Return Value

`string` |

at line 1800

### `prepareBasePath()`

`protected string prepareBasePath()`

Prepares the base path.

#### Return Value

`string` | base path

at line 1826

### `preparePathInfo()`

`protected string preparePathInfo()`

Prepares the path info.

#### Return Value

`string` | path info

at line 1856

### `initializeFormats()`

`protected static initializeFormats()`

Initializes HTTP request formats.

at line 1930

### `isFromTrustedProxy()`

`public bool isFromTrustedProxy()`

Indicates whether this request originated from a trusted proxy.

This can be useful to determine whether or not to trust the contents of a proxy-specific header.

#### Return Value

`bool` | true if the request came from a trusted proxy, false otherwise

## Source code

    <?php

    /*
     * This file is part of the Symfony package.
     *
     * (c) Fabien Potencier <fabien@symfony.com>
     *
     * For the full copyright and license information, please view the LICENSE
     * file that was distributed with this source code.
     */

    namespace App\Khan\Component\HttpFoundation;

    use \App\Khan\Component\HttpFoundation\Exception\ConflictingHeadersException;
    use \App\Khan\Component\HttpFoundation\Exception\SuspiciousOperationException;
    use \App\Khan\Component\HttpFoundation\Session\SessionInterface;

    /**
     * Request represents an HTTP request.
     *
     * The methods dealing with URL accept / return a raw path (% encoded):
     *   * getBasePath
     *   * getBaseUrl
     *   * getPathInfo
     *   * getRequestUri
     *   * getUri
     *   * getUriForPath
     *
     * @author Fabien Potencier <fabien@symfony.com>
     */
    class Request
    {
        const HEADER_FORWARDED = 0b00001; // When using RFC 7239
        const HEADER_X_FORWARDED_FOR = 0b00010;
        const HEADER_X_FORWARDED_HOST = 0b00100;
        const HEADER_X_FORWARDED_PROTO = 0b01000;
        const HEADER_X_FORWARDED_PORT = 0b10000;
        const HEADER_X_FORWARDED_ALL = 0b11110; // All "X-Forwarded-*" headers
        const HEADER_X_FORWARDED_AWS_ELB = 0b11010; // AWS ELB doesn't send X-Forwarded-Host

        const METHOD_HEAD = 'HEAD';
        const METHOD_GET = 'GET';
        const METHOD_POST = 'POST';
        const METHOD_PUT = 'PUT';
        const METHOD_PATCH = 'PATCH';
        const METHOD_DELETE = 'DELETE';
        const METHOD_PURGE = 'PURGE';
        const METHOD_OPTIONS = 'OPTIONS';
        const METHOD_TRACE = 'TRACE';
        const METHOD_CONNECT = 'CONNECT';

        /**
         * @var string[]
         */
        protected static $trustedProxies = array();

        /**
         * @var string[]
         */
        protected static $trustedHostPatterns = array();

        /**
         * @var string[]
         */
        protected static $trustedHosts = array();

        protected static $httpMethodParameterOverride = false;

        /**
         * Custom parameters.
         *
         * @var \Symfony\Component\HttpFoundation\ParameterBag
         */
        public $attributes;

        /**
         * Request body parameters ($_POST).
         *
         * @var \Symfony\Component\HttpFoundation\ParameterBag
         */
        public $request;

        /**
         * Query string parameters ($_GET).
         *
         * @var \Symfony\Component\HttpFoundation\ParameterBag
         */
        public $query;

        /**
         * Server and execution environment parameters ($_SERVER).
         *
         * @var \Symfony\Component\HttpFoundation\ServerBag
         */
        public $server;

        /**
         * Uploaded files ($_FILES).
         *
         * @var \Symfony\Component\HttpFoundation\FileBag
         */
        public $files;

        /**
         * Cookies ($_COOKIE).
         *
         * @var \Symfony\Component\HttpFoundation\ParameterBag
         */
        public $cookies;

        /**
         * Headers (taken from the $_SERVER).
         *
         * @var \Symfony\Component\HttpFoundation\HeaderBag
         */
        public $headers;

        /**
         * @var string|resource|false|null
         */
        protected $content;

        /**
         * @var array
         */
        protected $languages;

        /**
         * @var array
         */
        protected $charsets;

        /**
         * @var array
         */
        protected $encodings;

        /**
         * @var array
         */
        protected $acceptableContentTypes;

        /**
         * @var string
         */
        protected $pathInfo;

        /**
         * @var string
         */
        protected $requestUri;

        /**
         * @var string
         */
        protected $baseUrl;

        /**
         * @var string
         */
        protected $basePath;

        /**
         * @var string
         */
        protected $method;

        /**
         * @var string
         */
        protected $format;

        /**
         * @var \Symfony\Component\HttpFoundation\Session\SessionInterface
         */
        protected $session;

        /**
         * @var string
         */
        protected $locale;

        /**
         * @var string
         */
        protected $defaultLocale = 'en';

        /**
         * @var array
         */
        protected static $formats;

        protected static $requestFactory;

        private $isHostValid = true;
        private $isForwardedValid = true;

        private static $trustedHeaderSet = -1;

        private static $forwardedParams = array(
            self::HEADER_X_FORWARDED_FOR => 'for',
            self::HEADER_X_FORWARDED_HOST => 'host',
            self::HEADER_X_FORWARDED_PROTO => 'proto',
            self::HEADER_X_FORWARDED_PORT => 'host',
        );

        /**
         * Names for headers that can be trusted when
         * using trusted proxies.
         *
         * The FORWARDED header is the standard as of rfc7239.
         *
         * The other headers are non-standard, but widely used
         * by popular reverse proxies (like Apache mod_proxy or Amazon EC2).
         */
        private static $trustedHeaders = array(
            self::HEADER_FORWARDED => 'FORWARDED',
            self::HEADER_X_FORWARDED_FOR => 'X_FORWARDED_FOR',
            self::HEADER_X_FORWARDED_HOST => 'X_FORWARDED_HOST',
            self::HEADER_X_FORWARDED_PROTO => 'X_FORWARDED_PROTO',
            self::HEADER_X_FORWARDED_PORT => 'X_FORWARDED_PORT',
        );

        /**
         * @param array                $query      The GET parameters
         * @param array                $request    The POST parameters
         * @param array                $attributes The request attributes (parameters parsed from the PATH_INFO, ...)
         * @param array                $cookies    The COOKIE parameters
         * @param array                $files      The FILES parameters
         * @param array                $server     The SERVER parameters
         * @param string|resource|null $content    The raw body data
         */
        public function __construct(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null)
        {
            $this->initialize($query, $request, $attributes, $cookies, $files, $server, $content);
        }

        /**
         * Sets the parameters for this request.
         *
         * This method also re-initializes all properties.
         *
         * @param array                $query      The GET parameters
         * @param array                $request    The POST parameters
         * @param array                $attributes The request attributes (parameters parsed from the PATH_INFO, ...)
         * @param array                $cookies    The COOKIE parameters
         * @param array                $files      The FILES parameters
         * @param array                $server     The SERVER parameters
         * @param string|resource|null $content    The raw body data
         */
        public function initialize(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null)
        {
            $this->request = new ParameterBag($request);
            $this->query = new ParameterBag($query);
            $this->attributes = new ParameterBag($attributes);
            $this->cookies = new ParameterBag($cookies);
            $this->files = new FileBag($files);
            $this->server = new ServerBag($server);
            $this->headers = new HeaderBag($this->server->getHeaders());

            $this->content = $content;
            $this->languages = null;
            $this->charsets = null;
            $this->encodings = null;
            $this->acceptableContentTypes = null;
            $this->pathInfo = null;
            $this->requestUri = null;
            $this->baseUrl = null;
            $this->basePath = null;
            $this->method = null;
            $this->format = null;
        }

        /**
         * Creates a new request with values from PHP's super globals.
         *
         * @return static
         */
        public static function createFromGlobals()
        {
            $request = self::createRequestFromFactory($_GET, $_POST, array(), $_COOKIE, $_FILES, $_SERVER);

            if (0 === strpos($request->headers->get('CONTENT_TYPE'), 'application/x-www-form-urlencoded')
                && in_array(strtoupper($request->server->get('REQUEST_METHOD', 'GET')), array('PUT', 'DELETE', 'PATCH'))
            ) {
                parse_str($request->getContent(), $data);
                $request->request = new ParameterBag($data);
            }

            return $request;
        }

        /**
         * Creates a Request based on a given URI and configuration.
         *
         * The information contained in the URI always take precedence
         * over the other information (server and parameters).
         *
         * @param string               $uri        The URI
         * @param string               $method     The HTTP method
         * @param array                $parameters The query (GET) or request (POST) parameters
         * @param array                $cookies    The request cookies ($_COOKIE)
         * @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($uri, $method = 'GET', $parameters = array(), $cookies = array(), $files = array(), $server = array(), $content = null)
        {
            $server = array_replace(array(
                'SERVER_NAME' => 'localhost',
                'SERVER_PORT' => 80,
                'HTTP_HOST' => 'localhost',
                'HTTP_USER_AGENT' => 'Symfony',
                'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
                'HTTP_ACCEPT_LANGUAGE' => 'en-us,en;q=0.5',
                'HTTP_ACCEPT_CHARSET' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
                'REMOTE_ADDR' => '127.0.0.1',
                'SCRIPT_NAME' => '',
                'SCRIPT_FILENAME' => '',
                'SERVER_PROTOCOL' => 'HTTP/1.1',
                'REQUEST_TIME' => time(),
            ), $server);

            $server['PATH_INFO'] = '';
            $server['REQUEST_METHOD'] = strtoupper($method);

            $components = parse_url($uri);
            if (isset($components['host'])) {
                $server['SERVER_NAME'] = $components['host'];
                $server['HTTP_HOST'] = $components['host'];
            }

            if (isset($components['scheme'])) {
                if ('https' === $components['scheme']) {
                    $server['HTTPS'] = 'on';
                    $server['SERVER_PORT'] = 443;
                } else {
                    unset($server['HTTPS']);
                    $server['SERVER_PORT'] = 80;
                }
            }

            if (isset($components['port'])) {
                $server['SERVER_PORT'] = $components['port'];
                $server['HTTP_HOST'] = $server['HTTP_HOST'].':'.$components['port'];
            }

            if (isset($components['user'])) {
                $server['PHP_AUTH_USER'] = $components['user'];
            }

            if (isset($components['pass'])) {
                $server['PHP_AUTH_PW'] = $components['pass'];
            }

            if (!isset($components['path'])) {
                $components['path'] = '/';
            }

            switch (strtoupper($method)) {
                case 'POST':
                case 'PUT':
                case 'DELETE':
                    if (!isset($server['CONTENT_TYPE'])) {
                        $server['CONTENT_TYPE'] = 'application/x-www-form-urlencoded';
                    }
                    // no break
                case 'PATCH':
                    $request = $parameters;
                    $query = array();
                    break;
                default:
                    $request = array();
                    $query = $parameters;
                    break;
            }

            $queryString = '';
            if (isset($components['query'])) {
                parse_str(html_entity_decode($components['query']), $qs);

                if ($query) {
                    $query = array_replace($qs, $query);
                    $queryString = http_build_query($query, '', '&');
                } else {
                    $query = $qs;
                    $queryString = $components['query'];
                }
            } elseif ($query) {
                $queryString = http_build_query($query, '', '&');
            }

            $server['REQUEST_URI'] = $components['path'].('' !== $queryString ? '?'.$queryString : '');
            $server['QUERY_STRING'] = $queryString;

            return self::createRequestFromFactory($query, $request, array(), $cookies, $files, $server, $content);
        }

        /**
         * Sets a callable able to create a Request instance.
         *
         * This is mainly useful when you need to override the Request class
         * to keep BC with an existing system. It should not be used for any
         * other purpose.
         *
         * @param callable|null $callable A PHP callable
         */
        public static function setFactory($callable)
        {
            self::$requestFactory = $callable;
        }

        /**
         * Clones a request and overrides some of its parameters.
         *
         * @param array $query      The GET parameters
         * @param array $request    The POST parameters
         * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...)
         * @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)
        {
            $dup = clone $this;
            if (null !== $query) {
                $dup->query = new ParameterBag($query);
            }
            if (null !== $request) {
                $dup->request = new ParameterBag($request);
            }
            if (null !== $attributes) {
                $dup->attributes = new ParameterBag($attributes);
            }
            if (null !== $cookies) {
                $dup->cookies = new ParameterBag($cookies);
            }
            if (null !== $files) {
                $dup->files = new FileBag($files);
            }
            if (null !== $server) {
                $dup->server = new ServerBag($server);
                $dup->headers = new HeaderBag($dup->server->getHeaders());
            }
            $dup->languages = null;
            $dup->charsets = null;
            $dup->encodings = null;
            $dup->acceptableContentTypes = null;
            $dup->pathInfo = null;
            $dup->requestUri = null;
            $dup->baseUrl = null;
            $dup->basePath = null;
            $dup->method = null;
            $dup->format = null;

            if (!$dup->get('_format') && $this->get('_format')) {
                $dup->attributes->set('_format', $this->get('_format'));
            }

            if (!$dup->getRequestFormat(null)) {
                $dup->setRequestFormat($this->getRequestFormat(null));
            }

            return $dup;
        }

        /**
         * Clones the current request.
         *
         * Note that the session is not cloned as duplicated requests
         * are most of the time sub-requests of the main one.
         */
        public function __clone()
        {
            $this->query = clone $this->query;
            $this->request = clone $this->request;
            $this->attributes = clone $this->attributes;
            $this->cookies = clone $this->cookies;
            $this->files = clone $this->files;
            $this->server = clone $this->server;
            $this->headers = clone $this->headers;
        }

        /**
         * Returns the request as a string.
         *
         * @return string The request
         */
        public function __toString()
        {
            try {
                $content = $this->getContent();
            } catch (\LogicException $e) {
                return trigger_error($e, E_USER_ERROR);
            }

            $cookieHeader = '';
            $cookies = array();

            foreach ($this->cookies as $k => $v) {
                $cookies[] = $k.'='.$v;
            }

            if (!empty($cookies)) {
                $cookieHeader = 'Cookie: '.implode('; ', $cookies)."\r\n";
            }

            return
                sprintf('%s %s %s', $this->getMethod(), $this->getRequestUri(), $this->server->get('SERVER_PROTOCOL'))."\r\n".
                $this->headers.
                $cookieHeader."\r\n".
                $content;
        }

        /**
         * Overrides the PHP global variables according to this request instance.
         *
         * It overrides $_GET, $_POST, $_REQUEST, $_SERVER, $_COOKIE.
         * $_FILES is never overridden, see rfc1867
         */
        public function overrideGlobals()
        {
            $this->server->set('QUERY_STRING', static::normalizeQueryString(http_build_query($this->query->all(), '', '&')));

            $_GET = $this->query->all();
            $_POST = $this->request->all();
            $_SERVER = $this->server->all();
            $_COOKIE = $this->cookies->all();

            foreach ($this->headers->all() as $key => $value) {
                $key = strtoupper(str_replace('-', '_', $key));
                if (in_array($key, array('CONTENT_TYPE', 'CONTENT_LENGTH'))) {
                    $_SERVER[$key] = implode(', ', $value);
                } else {
                    $_SERVER['HTTP_'.$key] = implode(', ', $value);
                }
            }

            $request = array('g' => $_GET, 'p' => $_POST, 'c' => $_COOKIE);

            $requestOrder = ini_get('request_order') ?: ini_get('variables_order');
            $requestOrder = preg_replace('#[^cgp]#', '', strtolower($requestOrder)) ?: 'gp';

            $_REQUEST = array();
            foreach (str_split($requestOrder) as $order) {
                $_REQUEST = array_merge($_REQUEST, $request[$order]);
            }
        }

        /**
         * Sets a list of trusted proxies.
         *
         * You should only list the reverse proxies that you manage directly.
         *
         * @param array $proxies          A list of trusted proxies
         * @param int   $trustedHeaderSet A bit field of Request::HEADER_*, to set which headers to trust from your proxies
         *
         * @throws \InvalidArgumentException When $trustedHeaderSet is invalid
         */
        public static function setTrustedProxies(array $proxies, int $trustedHeaderSet)
        {
            self::$trustedProxies = $proxies;
            self::$trustedHeaderSet = $trustedHeaderSet;
        }

        /**
         * Gets the list of trusted proxies.
         *
         * @return array An array of trusted proxies
         */
        public static function getTrustedProxies()
        {
            return self::$trustedProxies;
        }

        /**
         * Gets the set of trusted headers from trusted proxies.
         *
         * @return int A bit field of Request::HEADER_* that defines which headers are trusted from your proxies
         */
        public static function getTrustedHeaderSet()
        {
            return self::$trustedHeaderSet;
        }

        /**
         * Sets a list of trusted host patterns.
         *
         * You should only list the hosts you manage using regexs.
         *
         * @param array $hostPatterns A list of trusted host patterns
         */
        public static function setTrustedHosts(array $hostPatterns)
        {
            self::$trustedHostPatterns = array_map(function ($hostPattern) {
                return sprintf('#%s#i', $hostPattern);
            }, $hostPatterns);
            // we need to reset trusted hosts on trusted host patterns change
            self::$trustedHosts = array();
        }

        /**
         * Gets the list of trusted host patterns.
         *
         * @return array An array of trusted host patterns
         */
        public static function getTrustedHosts()
        {
            return self::$trustedHostPatterns;
        }

        /**
         * Normalizes a query string.
         *
         * It builds a normalized query string, where keys/value pairs are alphabetized,
         * have consistent escaping and unneeded delimiters are removed.
         *
         * @param string $qs Query string
         *
         * @return string A normalized query string for the Request
         */
        public static function normalizeQueryString($qs)
        {
            if ('' == $qs) {
                return '';
            }

            parse_str($qs, $qs);
            ksort($qs);

            return http_build_query($qs, '', '&', PHP_QUERY_RFC3986);
        }

        /**
         * Enables support for the _method request parameter to determine the intended HTTP method.
         *
         * Be warned that enabling this feature might lead to CSRF issues in your code.
         * Check that you are using CSRF tokens when required.
         * If the HTTP method parameter override is enabled, an html-form with method "POST" can be altered
         * and used to send a "PUT" or "DELETE" request via the _method request parameter.
         * If these methods are not protected against CSRF, this presents a possible vulnerability.
         *
         * The HTTP method can only be overridden when the real HTTP method is POST.
         */
        public static function enableHttpMethodParameterOverride()
        {
            self::$httpMethodParameterOverride = true;
        }

        /**
         * Checks whether support for the _method request parameter is enabled.
         *
         * @return bool True when the _method request parameter is enabled, false otherwise
         */
        public static function getHttpMethodParameterOverride()
        {
            return self::$httpMethodParameterOverride;
        }

        /**
         * Gets a "parameter" value from any bag.
         *
         * This method is mainly useful for libraries that want to provide some flexibility. If you don't need the
         * flexibility in controllers, it is better to explicitly get request parameters from the appropriate
         * public property instead (attributes, query, request).
         *
         * Order of precedence: PATH (routing placeholders or custom attributes), GET, BODY
         *
         * @param string $key     The key
         * @param mixed  $default The default value if the parameter key does not exist
         *
         * @return mixed
         */
        public function get($key, $default = null)
        {
            if ($this !== $result = $this->attributes->get($key, $this)) {
                return $result;
            }

            if ($this !== $result = $this->query->get($key, $this)) {
                return $result;
            }

            if ($this !== $result = $this->request->get($key, $this)) {
                return $result;
            }

            return $default;
        }

        /**
         * Gets the Session.
         *
         * @return SessionInterface|null The session
         */
        public function getSession()
        {
            $session = $this->session;
            if (!$session instanceof SessionInterface && null !== $session) {
                $this->setSession($session = $session());
            }

            if (null === $session) {
                @trigger_error(sprintf('Calling "%s()" when no session has been set is deprecated since Symfony 4.1 and will throw an exception in 5.0. Use "hasSession()" instead.', __METHOD__), E_USER_DEPRECATED);
                // throw new \BadMethodCallException('Session has not been set');
            }

            return $session;
        }

        /**
         * Whether the request contains a Session which was started in one of the
         * previous requests.
         *
         * @return bool
         */
        public function hasPreviousSession()
        {
            // 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());
        }

        /**
         * Whether the request contains a Session object.
         *
         * This method does not give any information about the state of the session object,
         * like whether the session is started or not. It is just a way to check if this Request
         * is associated with a Session instance.
         *
         * @return bool true when the Request contains a Session object, false otherwise
         */
        public function hasSession()
        {
            return null !== $this->session;
        }

        /**
         * Sets the Session.
         *
         * @param SessionInterface $session The Session
         */
        public function setSession(SessionInterface $session)
        {
            $this->session = $session;
        }

        /**
         * @internal
         */
        public function setSessionFactory(callable $factory)
        {
            $this->session = $factory;
        }

        /**
         * Returns the client IP addresses.
         *
         * In the returned array the most trusted IP address is first, and the
         * least trusted one last. The "real" client IP address is the last one,
         * but this is also the least trusted one. Trusted proxies are stripped.
         *
         * Use this method carefully; you should use getClientIp() instead.
         *
         * @return array The client IP addresses
         *
         * @see getClientIp()
         */
        public function getClientIps()
        {
            $ip = $this->server->get('REMOTE_ADDR');

            if (!$this->isFromTrustedProxy()) {
                return array($ip);
            }

            return $this->getTrustedValues(self::HEADER_X_FORWARDED_FOR, $ip) ?: array($ip);
        }

        /**
         * Returns the client IP address.
         *
         * This method can read the client IP address from the "X-Forwarded-For" header
         * when trusted proxies were set via "setTrustedProxies()". The "X-Forwarded-For"
         * header value is a comma+space separated list of IP addresses, the left-most
         * being the original client, and each successive proxy that passed the request
         * adding the IP address where it received the request from.
         *
         * @return string|null The client IP address
         *
         * @see getClientIps()
         * @see http://en.wikipedia.org/wiki/X-Forwarded-For
         */
        public function getClientIp()
        {
            $ipAddresses = $this->getClientIps();

            return $ipAddresses[0];
        }

        /**
         * Returns current script name.
         *
         * @return string
         */
        public function getScriptName()
        {
            return $this->server->get('SCRIPT_NAME', $this->server->get('ORIG_SCRIPT_NAME', ''));
        }

        /**
         * Returns the path being requested relative to the executed script.
         *
         * The path info always starts with a /.
         *
         * Suppose this request is instantiated from /mysite on localhost:
         *
         *  * http://localhost/mysite              returns an empty string
         *  * http://localhost/mysite/about        returns '/about'
         *  * http://localhost/mysite/enco%20ded   returns '/enco%20ded'
         *  * http://localhost/mysite/about?var=1  returns '/about'
         *
         * @return string The raw path (i.e. not urldecoded)
         */
        public function getPathInfo()
        {
            if (null === $this->pathInfo) {
                $this->pathInfo = $this->preparePathInfo();
            }

            return $this->pathInfo;
        }

        /**
         * Returns the root path from which this request is executed.
         *
         * Suppose that an index.php file instantiates this request object:
         *
         *  * http://localhost/index.php         returns an empty string
         *  * http://localhost/index.php/page    returns an empty string
         *  * http://localhost/web/index.php     returns '/web'
         *  * http://localhost/we%20b/index.php  returns '/we%20b'
         *
         * @return string The raw path (i.e. not urldecoded)
         */
        public function getBasePath()
        {
            if (null === $this->basePath) {
                $this->basePath = $this->prepareBasePath();
            }

            return $this->basePath;
        }

        /**
         * Returns the root URL from which this request is executed.
         *
         * The base URL never ends with a /.
         *
         * This is similar to getBasePath(), except that it also includes the
         * script filename (e.g. index.php) if one exists.
         *
         * @return string The raw URL (i.e. not urldecoded)
         */
        public function getBaseUrl()
        {
            if (null === $this->baseUrl) {
                $this->baseUrl = $this->prepareBaseUrl();
            }

            return $this->baseUrl;
        }

        /**
         * Gets the request's scheme.
         *
         * @return string
         */
        public function getScheme()
        {
            return $this->isSecure() ? 'https' : 'http';
        }

        /**
         * Returns the port on which the request is made.
         *
         * This method can read the client port from the "X-Forwarded-Port" header
         * when trusted proxies were set via "setTrustedProxies()".
         *
         * The "X-Forwarded-Port" header must contain the client port.
         *
         * @return int|string can be a string if fetched from the server bag
         */
        public function getPort()
        {
            if ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_X_FORWARDED_PORT)) {
                $host = $host[0];
            } elseif ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_X_FORWARDED_HOST)) {
                $host = $host[0];
            } elseif (!$host = $this->headers->get('HOST')) {
                return $this->server->get('SERVER_PORT');
            }

            if ('[' === $host[0]) {
                $pos = strpos($host, ':', strrpos($host, ']'));
            } else {
                $pos = strrpos($host, ':');
            }

            if (false !== $pos) {
                return (int) substr($host, $pos + 1);
            }

            return 'https' === $this->getScheme() ? 443 : 80;
        }

        /**
         * Returns the user.
         *
         * @return string|null
         */
        public function getUser()
        {
            return $this->headers->get('PHP_AUTH_USER');
        }

        /**
         * Returns the password.
         *
         * @return string|null
         */
        public function getPassword()
        {
            return $this->headers->get('PHP_AUTH_PW');
        }

        /**
         * Gets the user info.
         *
         * @return string A user name and, optionally, scheme-specific information about how to gain authorization to access the server
         */
        public function getUserInfo()
        {
            $userinfo = $this->getUser();

            $pass = $this->getPassword();
            if ('' != $pass) {
                $userinfo .= ":$pass";
            }

            return $userinfo;
        }

        /**
         * 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()
        {
            $scheme = $this->getScheme();
            $port = $this->getPort();

            if (('http' == $scheme && 80 == $port) || ('https' == $scheme && 443 == $port)) {
                return $this->getHost();
            }

            return $this->getHost().':'.$port;
        }

        /**
         * Returns the requested URI (path and query string).
         *
         * @return string The raw URI (i.e. not URI decoded)
         */
        public function getRequestUri()
        {
            if (null === $this->requestUri) {
                $this->requestUri = $this->prepareRequestUri();
            }

            return $this->requestUri;
        }

        /**
         * Gets the scheme and HTTP host.
         *
         * If the URL was called with basic authentication, the user
         * and the password are not added to the generated string.
         *
         * @return string The scheme and HTTP host
         */
        public function getSchemeAndHttpHost()
        {
            return $this->getScheme().'://'.$this->getHttpHost();
        }

        /**
         * Generates a normalized URI (URL) for the Request.
         *
         * @return string A normalized URI (URL) for the Request
         *
         * @see getQueryString()
         */
        public function getUri()
        {
            if (null !== $qs = $this->getQueryString()) {
                $qs = '?'.$qs;
            }

            return $this->getSchemeAndHttpHost().$this->getBaseUrl().$this->getPathInfo().$qs;
        }

        /**
         * Generates a normalized URI for the given path.
         *
         * @param string $path A path to use instead of the current one
         *
         * @return string The normalized URI for the path
         */
        public function getUriForPath($path)
        {
            return $this->getSchemeAndHttpHost().$this->getBaseUrl().$path;
        }

        /**
         * Returns the path as relative reference from the current Request path.
         *
         * Only the URIs path component (no schema, host etc.) is relevant and must be given.
         * Both paths must be absolute and not contain relative parts.
         * Relative URLs from one resource to another are useful when generating self-contained downloadable document archives.
         * Furthermore, they can be used to reduce the link size in documents.
         *
         * Example target paths, given a base path of "/a/b/c/d":
         * - "/a/b/c/d"     -> ""
         * - "/a/b/c/"      -> "./"
         * - "/a/b/"        -> "../"
         * - "/a/b/c/other" -> "other"
         * - "/a/x/y"       -> "../../x/y"
         *
         * @param string $path The target path
         *
         * @return string The relative target path
         */
        public function getRelativeUriForPath($path)
        {
            // be sure that we are dealing with an absolute path
            if (!isset($path[0]) || '/' !== $path[0]) {
                return $path;
            }

            if ($path === $basePath = $this->getPathInfo()) {
                return '';
            }

            $sourceDirs = explode('/', isset($basePath[0]) && '/' === $basePath[0] ? substr($basePath, 1) : $basePath);
            $targetDirs = explode('/', isset($path[0]) && '/' === $path[0] ? substr($path, 1) : $path);
            array_pop($sourceDirs);
            $targetFile = array_pop($targetDirs);

            foreach ($sourceDirs as $i => $dir) {
                if (isset($targetDirs[$i]) && $dir === $targetDirs[$i]) {
                    unset($sourceDirs[$i], $targetDirs[$i]);
                } else {
                    break;
                }
            }

            $targetDirs[] = $targetFile;
            $path = str_repeat('../', count($sourceDirs)).implode('/', $targetDirs);

            // A reference to the same base directory or an empty subdirectory must be prefixed with "./".
            // This also applies to a segment with a colon character (e.g., "file:colon") that cannot be used
            // as the first segment of a relative-path reference, as it would be mistaken for a scheme name
            // (see http://tools.ietf.org/html/rfc3986#section-4.2).
            return !isset($path[0]) || '/' === $path[0]
                || false !== ($colonPos = strpos($path, ':')) && ($colonPos < ($slashPos = strpos($path, '/')) || false === $slashPos)
                ? "./$path" : $path;
        }

        /**
         * Generates the normalized query string for the Request.
         *
         * It builds a normalized query string, where keys/value pairs are alphabetized
         * and have consistent escaping.
         *
         * @return string|null A normalized query string for the Request
         */
        public function getQueryString()
        {
            $qs = static::normalizeQueryString($this->server->get('QUERY_STRING'));

            return '' === $qs ? null : $qs;
        }

        /**
         * Checks whether the request is secure or not.
         *
         * This method can read the client protocol from the "X-Forwarded-Proto" header
         * when trusted proxies were set via "setTrustedProxies()".
         *
         * The "X-Forwarded-Proto" header must contain the protocol: "https" or "http".
         *
         * @return bool
         */
        public function isSecure()
        {
            if ($this->isFromTrustedProxy() && $proto = $this->getTrustedValues(self::HEADER_X_FORWARDED_PROTO)) {
                return in_array(strtolower($proto[0]), array('https', 'on', 'ssl', '1'), true);
            }

            $https = $this->server->get('HTTPS');

            return !empty($https) && 'off' !== strtolower($https);
        }

        /**
         * Returns the host name.
         *
         * This method can read the client host name from the "X-Forwarded-Host" header
         * when trusted proxies were set via "setTrustedProxies()".
         *
         * 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()
        {
            if ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_X_FORWARDED_HOST)) {
                $host = $host[0];
            } elseif (!$host = $this->headers->get('HOST')) {
                if (!$host = $this->server->get('SERVER_NAME')) {
                    $host = $this->server->get('SERVER_ADDR', '');
                }
            }

            // trim and remove port number from host
            // host is lowercase as per RFC 952/2181
            $host = strtolower(preg_replace('/:\d+$/', '', trim($host)));

            // as the host can come from the user (HTTP_HOST and depending on the configuration, SERVER_NAME too can come from the user)
            // check that it does not contain forbidden characters (see RFC 952 and RFC 2181)
            // use preg_replace() instead of preg_match() to prevent DoS attacks with long host names
            if ($host && '' !== preg_replace('/(?:^\[)?[a-zA-Z0-9-:\]_]+\.?/', '', $host)) {
                if (!$this->isHostValid) {
                    return '';
                }
                $this->isHostValid = false;

                throw new SuspiciousOperationException(sprintf('Invalid Host "%s".', $host));
            }

            if (count(self::$trustedHostPatterns) > 0) {
                // to avoid host header injection attacks, you should provide a list of trusted host patterns

                if (in_array($host, self::$trustedHosts)) {
                    return $host;
                }

                foreach (self::$trustedHostPatterns as $pattern) {
                    if (preg_match($pattern, $host)) {
                        self::$trustedHosts[] = $host;

                        return $host;
                    }
                }

                if (!$this->isHostValid) {
                    return '';
                }
                $this->isHostValid = false;

                throw new SuspiciousOperationException(sprintf('Untrusted Host "%s".', $host));
            }

            return $host;
        }

        /**
         * Sets the request method.
         *
         * @param string $method
         */
        public function setMethod($method)
        {
            $this->method = null;
            $this->server->set('REQUEST_METHOD', $method);
        }

        /**
         * Gets the request "intended" method.
         *
         * If the X-HTTP-Method-Override header is set, and if the method is a POST,
         * then it is used to determine the "real" intended HTTP method.
         *
         * The _method request parameter can also be used to determine the HTTP method,
         * but only if enableHttpMethodParameterOverride() has been called.
         *
         * The method is always an uppercased string.
         *
         * @return string The request method
         *
         * @see getRealMethod()
         */
        public function getMethod()
        {
            if (null === $this->method) {
                $this->method = strtoupper($this->server->get('REQUEST_METHOD', 'GET'));

                if ('POST' === $this->method) {
                    if ($method = $this->headers->get('X-HTTP-METHOD-OVERRIDE')) {
                        $this->method = strtoupper($method);
                    } elseif (self::$httpMethodParameterOverride) {
                        $this->method = strtoupper($this->request->get('_method', $this->query->get('_method', 'POST')));
                    }
                }
            }

            return $this->method;
        }

        /**
         * Gets the "real" request method.
         *
         * @return string The request method
         *
         * @see getMethod()
         */
        public function getRealMethod()
        {
            return strtoupper($this->server->get('REQUEST_METHOD', 'GET'));
        }

        /**
         * Gets the mime type associated with the format.
         *
         * @param string $format The format
         *
         * @return string The associated mime type (null if not found)
         */
        public function getMimeType($format)
        {
            if (null === static::$formats) {
                static::initializeFormats();
            }

            return isset(static::$formats[$format]) ? static::$formats[$format][0] : null;
        }

        /**
         * Gets the mime types associated with the format.
         *
         * @param string $format The format
         *
         * @return array The associated mime types
         */
        public static function getMimeTypes($format)
        {
            if (null === static::$formats) {
                static::initializeFormats();
            }

            return isset(static::$formats[$format]) ? static::$formats[$format] : array();
        }

        /**
         * Gets the format associated with the mime type.
         *
         * @param string $mimeType The associated mime type
         *
         * @return string|null The format (null if not found)
         */
        public function getFormat($mimeType)
        {
            $canonicalMimeType = null;
            if (false !== $pos = strpos($mimeType, ';')) {
                $canonicalMimeType = substr($mimeType, 0, $pos);
            }

            if (null === static::$formats) {
                static::initializeFormats();
            }

            foreach (static::$formats as $format => $mimeTypes) {
                if (in_array($mimeType, (array) $mimeTypes)) {
                    return $format;
                }
                if (null !== $canonicalMimeType && in_array($canonicalMimeType, (array) $mimeTypes)) {
                    return $format;
                }
            }
        }

        /**
         * Associates a format with mime types.
         *
         * @param string       $format    The format
         * @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($format, $mimeTypes)
        {
            if (null === static::$formats) {
                static::initializeFormats();
            }

            static::$formats[$format] = is_array($mimeTypes) ? $mimeTypes : array($mimeTypes);
        }

        /**
         * Gets the request format.
         *
         * Here is the process to determine the format:
         *
         *  * format defined by the user (with setRequestFormat())
         *  * _format request attribute
         *  * $default
         *
         * @param string $default The default format
         *
         * @return string The request format
         */
        public function getRequestFormat($default = 'html')
        {
            if (null === $this->format) {
                $this->format = $this->attributes->get('_format');
            }

            return null === $this->format ? $default : $this->format;
        }

        /**
         * Sets the request format.
         *
         * @param string $format The request format
         */
        public function setRequestFormat($format)
        {
            $this->format = $format;
        }

        /**
         * Gets the format associated with the request.
         *
         * @return string|null The format (null if no content type is present)
         */
        public function getContentType()
        {
            return $this->getFormat($this->headers->get('CONTENT_TYPE'));
        }

        /**
         * Sets the default locale.
         *
         * @param string $locale
         */
        public function setDefaultLocale($locale)
        {
            $this->defaultLocale = $locale;

            if (null === $this->locale) {
                $this->setPhpDefaultLocale($locale);
            }
        }

        /**
         * Get the default locale.
         *
         * @return string
         */
        public function getDefaultLocale()
        {
            return $this->defaultLocale;
        }

        /**
         * Sets the locale.
         *
         * @param string $locale
         */
        public function setLocale($locale)
        {
            $this->setPhpDefaultLocale($this->locale = $locale);
        }

        /**
         * Get the locale.
         *
         * @return string
         */
        public function getLocale()
        {
            return null === $this->locale ? $this->defaultLocale : $this->locale;
        }

        /**
         * Checks if the request method is of specified type.
         *
         * @param string $method Uppercase request method (GET, POST etc)
         *
         * @return bool
         */
        public function isMethod($method)
        {
            return $this->getMethod() === strtoupper($method);
        }

        /**
         * Checks whether or not the method is safe.
         *
         * @see https://tools.ietf.org/html/rfc7231#section-4.2.1
         *
         * @param bool $andCacheable Adds the additional condition that the method should be cacheable. True by default.
         *
         * @return bool
         */
        public function isMethodSafe(/* $andCacheable = true */)
        {
            if (!func_num_args() || func_get_arg(0)) {
                // setting $andCacheable to false should be deprecated in 4.1
                throw new \BadMethodCallException('Checking only for cacheable HTTP methods with Symfony\Component\HttpFoundation\Request::isMethodSafe() is not supported.');
            }

            return in_array($this->getMethod(), array('GET', 'HEAD', 'OPTIONS', 'TRACE'));
        }

        /**
         * Checks whether or not the method is idempotent.
         *
         * @return bool
         */
        public function isMethodIdempotent()
        {
            return in_array($this->getMethod(), array('HEAD', 'GET', 'PUT', 'DELETE', 'TRACE', 'OPTIONS', 'PURGE'));
        }

        /**
         * Checks whether the method is cacheable or not.
         *
         * @see https://tools.ietf.org/html/rfc7231#section-4.2.3
         *
         * @return bool
         */
        public function isMethodCacheable()
        {
            return in_array($this->getMethod(), array('GET', 'HEAD'));
        }

        /**
         * Returns the protocol version.
         *
         * If the application is behind a proxy, the protocol version used in the
         * requests between the client and the proxy and between the proxy and the
         * 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
         */
        public function getProtocolVersion()
        {
            if ($this->isFromTrustedProxy()) {
                preg_match('~^(HTTP/)?([1-9]\.[0-9]) ~', $this->headers->get('Via'), $matches);

                if ($matches) {
                    return 'HTTP/'.$matches[2];
                }
            }

            return $this->server->get('SERVER_PROTOCOL');
        }

        /**
         * Returns the request body content.
         *
         * @param bool $asResource If true, a resource will be returned
         *
         * @return string|resource The request body content or a resource to read the body stream
         *
         * @throws \LogicException
         */
        public function getContent($asResource = false)
        {
            $currentContentIsResource = is_resource($this->content);

            if (true === $asResource) {
                if ($currentContentIsResource) {
                    rewind($this->content);

                    return $this->content;
                }

                // Content passed in parameter (test)
                if (is_string($this->content)) {
                    $resource = fopen('php://temp', 'r+');
                    fwrite($resource, $this->content);
                    rewind($resource);

                    return $resource;
                }

                $this->content = false;

                return fopen('php://input', 'rb');
            }

            if ($currentContentIsResource) {
                rewind($this->content);

                return stream_get_contents($this->content);
            }

            if (null === $this->content || false === $this->content) {
                $this->content = file_get_contents('php://input');
            }

            return $this->content;
        }

        /**
         * Gets the Etags.
         *
         * @return array The entity tags
         */
        public function getETags()
        {
            return preg_split('/\s*,\s*/', $this->headers->get('if_none_match'), null, PREG_SPLIT_NO_EMPTY);
        }

        /**
         * @return bool
         */
        public function isNoCache()
        {
            return $this->headers->hasCacheControlDirective('no-cache') || 'no-cache' == $this->headers->get('Pragma');
        }

        /**
         * Returns the preferred language.
         *
         * @param array $locales An array of ordered available locales
         *
         * @return string|null The preferred locale
         */
        public function getPreferredLanguage(array $locales = null)
        {
            $preferredLanguages = $this->getLanguages();

            if (empty($locales)) {
                return isset($preferredLanguages[0]) ? $preferredLanguages[0] : null;
            }

            if (!$preferredLanguages) {
                return $locales[0];
            }

            $extendedPreferredLanguages = array();
            foreach ($preferredLanguages as $language) {
                $extendedPreferredLanguages[] = $language;
                if (false !== $position = strpos($language, '_')) {
                    $superLanguage = substr($language, 0, $position);
                    if (!in_array($superLanguage, $preferredLanguages)) {
                        $extendedPreferredLanguages[] = $superLanguage;
                    }
                }
            }

            $preferredLanguages = array_values(array_intersect($extendedPreferredLanguages, $locales));

            return isset($preferredLanguages[0]) ? $preferredLanguages[0] : $locales[0];
        }

        /**
         * Gets a list of languages acceptable by the client browser.
         *
         * @return array Languages ordered in the user browser preferences
         */
        public function getLanguages()
        {
            if (null !== $this->languages) {
                return $this->languages;
            }

            $languages = AcceptHeader::fromString($this->headers->get('Accept-Language'))->all();
            $this->languages = array();
            foreach ($languages as $lang => $acceptHeaderItem) {
                if (false !== strpos($lang, '-')) {
                    $codes = explode('-', $lang);
                    if ('i' === $codes[0]) {
                        // Language not listed in ISO 639 that are not variants
                        // of any listed language, which can be registered with the
                        // i-prefix, such as i-cherokee
                        if (count($codes) > 1) {
                            $lang = $codes[1];
                        }
                    } else {
                        for ($i = 0, $max = count($codes); $i < $max; ++$i) {
                            if (0 === $i) {
                                $lang = strtolower($codes[0]);
                            } else {
                                $lang .= '_'.strtoupper($codes[$i]);
                            }
                        }
                    }
                }

                $this->languages[] = $lang;
            }

            return $this->languages;
        }

        /**
         * Gets a list of charsets acceptable by the client browser.
         *
         * @return array List of charsets in preferable order
         */
        public function getCharsets()
        {
            if (null !== $this->charsets) {
                return $this->charsets;
            }

            return $this->charsets = array_keys(AcceptHeader::fromString($this->headers->get('Accept-Charset'))->all());
        }

        /**
         * Gets a list of encodings acceptable by the client browser.
         *
         * @return array List of encodings in preferable order
         */
        public function getEncodings()
        {
            if (null !== $this->encodings) {
                return $this->encodings;
            }

            return $this->encodings = array_keys(AcceptHeader::fromString($this->headers->get('Accept-Encoding'))->all());
        }

        /**
         * Gets a list of content types acceptable by the client browser.
         *
         * @return array List of content types in preferable order
         */
        public function getAcceptableContentTypes()
        {
            if (null !== $this->acceptableContentTypes) {
                return $this->acceptableContentTypes;
            }

            return $this->acceptableContentTypes = array_keys(AcceptHeader::fromString($this->headers->get('Accept'))->all());
        }

        /**
         * Returns true if the request is a XMLHttpRequest.
         *
         * It works if your JavaScript library sets an X-Requested-With HTTP header.
         * It is known to work with common JavaScript frameworks:
         *
         * @see http://en.wikipedia.org/wiki/List_of_Ajax_frameworks#JavaScript
         *
         * @return bool true if the request is an XMLHttpRequest, false otherwise
         */
        public function isXmlHttpRequest()
        {
            return 'XMLHttpRequest' == $this->headers->get('X-Requested-With');
        }

        /*
         * The following methods are derived from code of the Zend Framework (1.10dev - 2010-01-24)
         *
         * Code subject to the new BSD license (http://framework.zend.com/license/new-bsd).
         *
         * Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
         */

        protected function prepareRequestUri()
        {
            $requestUri = '';

            if ($this->headers->has('X_ORIGINAL_URL')) {
                // IIS with Microsoft Rewrite Module
                $requestUri = $this->headers->get('X_ORIGINAL_URL');
                $this->headers->remove('X_ORIGINAL_URL');
                $this->server->remove('HTTP_X_ORIGINAL_URL');
                $this->server->remove('UNENCODED_URL');
                $this->server->remove('IIS_WasUrlRewritten');
            } elseif ($this->headers->has('X_REWRITE_URL')) {
                // IIS with ISAPI_Rewrite
                $requestUri = $this->headers->get('X_REWRITE_URL');
                $this->headers->remove('X_REWRITE_URL');
            } elseif ('1' == $this->server->get('IIS_WasUrlRewritten') && '' != $this->server->get('UNENCODED_URL')) {
                // IIS7 with URL Rewrite: make sure we get the unencoded URL (double slash problem)
                $requestUri = $this->server->get('UNENCODED_URL');
                $this->server->remove('UNENCODED_URL');
                $this->server->remove('IIS_WasUrlRewritten');
            } elseif ($this->server->has('REQUEST_URI')) {
                $requestUri = $this->server->get('REQUEST_URI');
                // HTTP proxy reqs setup request URI with scheme and host [and port] + the URL path, only use URL path
                $schemeAndHttpHost = $this->getSchemeAndHttpHost();
                if (0 === strpos($requestUri, $schemeAndHttpHost)) {
                    $requestUri = substr($requestUri, strlen($schemeAndHttpHost));
                }
            } elseif ($this->server->has('ORIG_PATH_INFO')) {
                // IIS 5.0, PHP as CGI
                $requestUri = $this->server->get('ORIG_PATH_INFO');
                if ('' != $this->server->get('QUERY_STRING')) {
                    $requestUri .= '?'.$this->server->get('QUERY_STRING');
                }
                $this->server->remove('ORIG_PATH_INFO');
            }

            // normalize the request URI to ease creating sub-requests from this request
            $this->server->set('REQUEST_URI', $requestUri);

            return $requestUri;
        }

        /**
         * Prepares the base URL.
         *
         * @return string
         */
        protected function prepareBaseUrl()
        {
            $filename = basename($this->server->get('SCRIPT_FILENAME'));

            if (basename($this->server->get('SCRIPT_NAME')) === $filename) {
                $baseUrl = $this->server->get('SCRIPT_NAME');
            } elseif (basename($this->server->get('PHP_SELF')) === $filename) {
                $baseUrl = $this->server->get('PHP_SELF');
            } elseif (basename($this->server->get('ORIG_SCRIPT_NAME')) === $filename) {
                $baseUrl = $this->server->get('ORIG_SCRIPT_NAME'); // 1and1 shared hosting compatibility
            } else {
                // Backtrack up the script_filename to find the portion matching
                // php_self
                $path = $this->server->get('PHP_SELF', '');
                $file = $this->server->get('SCRIPT_FILENAME', '');
                $segs = explode('/', trim($file, '/'));
                $segs = array_reverse($segs);
                $index = 0;
                $last = count($segs);
                $baseUrl = '';
                do {
                    $seg = $segs[$index];
                    $baseUrl = '/'.$seg.$baseUrl;
                    ++$index;
                } while ($last > $index && (false !== $pos = strpos($path, $baseUrl)) && 0 != $pos);
            }

            // Does the baseUrl have anything in common with the request_uri?
            $requestUri = $this->getRequestUri();
            if ('' !== $requestUri && '/' !== $requestUri[0]) {
                $requestUri = '/'.$requestUri;
            }

            if ($baseUrl && false !== $prefix = $this->getUrlencodedPrefix($requestUri, $baseUrl)) {
                // full $baseUrl matches
                return $prefix;
            }

            if ($baseUrl && false !== $prefix = $this->getUrlencodedPrefix($requestUri, rtrim(dirname($baseUrl), '/'.DIRECTORY_SEPARATOR).'/')) {
                // directory portion of $baseUrl matches
                return rtrim($prefix, '/'.DIRECTORY_SEPARATOR);
            }

            $truncatedRequestUri = $requestUri;
            if (false !== $pos = strpos($requestUri, '?')) {
                $truncatedRequestUri = substr($requestUri, 0, $pos);
            }

            $basename = basename($baseUrl);
            if (empty($basename) || !strpos(rawurldecode($truncatedRequestUri), $basename)) {
                // no match whatsoever; set it blank
                return '';
            }

            // If using mod_rewrite or ISAPI_Rewrite strip the script filename
            // out of baseUrl. $pos !== 0 makes sure it is not matching a value
            // from PATH_INFO or QUERY_STRING
            if (strlen($requestUri) >= strlen($baseUrl) && (false !== $pos = strpos($requestUri, $baseUrl)) && 0 !== $pos) {
                $baseUrl = substr($requestUri, 0, $pos + strlen($baseUrl));
            }

            return rtrim($baseUrl, '/'.DIRECTORY_SEPARATOR);
        }

        /**
         * Prepares the base path.
         *
         * @return string base path
         */
        protected function prepareBasePath()
        {
            $baseUrl = $this->getBaseUrl();
            if (empty($baseUrl)) {
                return '';
            }

            $filename = basename($this->server->get('SCRIPT_FILENAME'));
            if (basename($baseUrl) === $filename) {
                $basePath = dirname($baseUrl);
            } else {
                $basePath = $baseUrl;
            }

            if ('\\' === DIRECTORY_SEPARATOR) {
                $basePath = str_replace('\\', '/', $basePath);
            }

            return rtrim($basePath, '/');
        }

        /**
         * Prepares the path info.
         *
         * @return string path info
         */
        protected function preparePathInfo()
        {
            if (null === ($requestUri = $this->getRequestUri())) {
                return '/';
            }

            // Remove the query string from REQUEST_URI
            if (false !== $pos = strpos($requestUri, '?')) {
                $requestUri = substr($requestUri, 0, $pos);
            }
            if ('' !== $requestUri && '/' !== $requestUri[0]) {
                $requestUri = '/'.$requestUri;
            }

            if (null === ($baseUrl = $this->getBaseUrl())) {
                return $requestUri;
            }

            $pathInfo = substr($requestUri, strlen($baseUrl));
            if (false === $pathInfo || '' === $pathInfo) {
                // If substr() returns false then PATH_INFO is set to an empty string
                return '/';
            }

            return (string) $pathInfo;
        }

        /**
         * Initializes HTTP request formats.
         */
        protected static function initializeFormats()
        {
            static::$formats = array(
                'html' => array('text/html', 'application/xhtml+xml'),
                'txt' => array('text/plain'),
                'js' => array('application/javascript', 'application/x-javascript', 'text/javascript'),
                'css' => array('text/css'),
                'json' => array('application/json', 'application/x-json'),
                'jsonld' => array('application/ld+json'),
                'xml' => array('text/xml', 'application/xml', 'application/x-xml'),
                'rdf' => array('application/rdf+xml'),
                'atom' => array('application/atom+xml'),
                'rss' => array('application/rss+xml'),
                'form' => array('application/x-www-form-urlencoded'),
            );
        }

        private function setPhpDefaultLocale(string $locale)
        {
            // if either the class Locale doesn't exist, or an exception is thrown when
            // setting the default locale, the intl module is not installed, and
            // the call can be ignored:
            try {
                if (class_exists('Locale', false)) {
                    \Locale::setDefault($locale);
                }
            } catch (\Exception $e) {
            }
        }

        /*
         * Returns the prefix as encoded in the string when the string starts with
         * the given prefix, false otherwise.
         *
         * @return string|false The prefix as it is encoded in $string, or false
         */
        private function getUrlencodedPrefix(string $string, string $prefix)
        {
            if (0 !== strpos(rawurldecode($string), $prefix)) {
                return false;
            }

            $len = strlen($prefix);

            if (preg_match(sprintf('#^(%%[[:xdigit:]]{2}|.){%d}#', $len), $string, $match)) {
                return $match[0];
            }

            return false;
        }

        private static function createRequestFromFactory(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null)
        {
            if (self::$requestFactory) {
                $request = call_user_func(self::$requestFactory, $query, $request, $attributes, $cookies, $files, $server, $content);

                if (!$request instanceof self) {
                    throw new \LogicException('The Request factory must return an instance of Symfony\Component\HttpFoundation\Request.');
                }

                return $request;
            }

            return new static($query, $request, $attributes, $cookies, $files, $server, $content);
        }

        /**
         * Indicates whether this request originated from a trusted proxy.
         *
         * This can be useful to determine whether or not to trust the
         * contents of a proxy-specific header.
         *
         * @return bool true if the request came from a trusted proxy, false otherwise
         */
        public function isFromTrustedProxy()
        {
            return self::$trustedProxies && IpUtils::checkIp($this->server->get('REMOTE_ADDR'), self::$trustedProxies);
        }

        private function getTrustedValues($type, $ip = null)
        {
            $clientValues = array();
            $forwardedValues = array();

            if ((self::$trustedHeaderSet & $type) && $this->headers->has(self::$trustedHeaders[$type])) {
                foreach (explode(',', $this->headers->get(self::$trustedHeaders[$type])) as $v) {
                    $clientValues[] = (self::HEADER_X_FORWARDED_PORT === $type ? '0.0.0.0:' : '').trim($v);
                }
            }

            if ((self::$trustedHeaderSet & self::HEADER_FORWARDED) && $this->headers->has(self::$trustedHeaders[self::HEADER_FORWARDED])) {
                $forwardedValues = $this->headers->get(self::$trustedHeaders[self::HEADER_FORWARDED]);
                $forwardedValues = preg_match_all(sprintf('{(?:%s)=(?:"?\[?)([a-zA-Z0-9\.:_\-/]*+)}', self::$forwardedParams[$type]), $forwardedValues, $matches) ? $matches[1] : array();
            }

            if (null !== $ip) {
                $clientValues = $this->normalizeAndFilterClientIps($clientValues, $ip);
                $forwardedValues = $this->normalizeAndFilterClientIps($forwardedValues, $ip);
            }

            if ($forwardedValues === $clientValues || !$clientValues) {
                return $forwardedValues;
            }

            if (!$forwardedValues) {
                return $clientValues;
            }

            if (!$this->isForwardedValid) {
                return null !== $ip ? array('0.0.0.0', $ip) : array();
            }
            $this->isForwardedValid = false;

            throw new ConflictingHeadersException(sprintf('The request has both a trusted "%s" header and a trusted "%s" header, conflicting with each other. You should either configure your proxy to remove one of them, or configure your project to distrust the offending one.', self::$trustedHeaders[self::HEADER_FORWARDED], self::$trustedHeaders[$type]));
        }

        private function normalizeAndFilterClientIps(array $clientIps, $ip)
        {
            if (!$clientIps) {
                return array();
            }
            $clientIps[] = $ip; // Complete the IP chain with the IP the request actually came from
            $firstTrustedIp = null;

            foreach ($clientIps as $key => $clientIp) {
                // Remove port (unfortunately, it does happen)
                if (preg_match('{((?:\d+\.){3}\d+)\:\d+}', $clientIp, $match)) {
                    $clientIps[$key] = $clientIp = $match[1];
                }

                if (!filter_var($clientIp, FILTER_VALIDATE_IP)) {
                    unset($clientIps[$key]);

                    continue;
                }

                if (IpUtils::checkIp($clientIp, self::$trustedProxies)) {
                    unset($clientIps[$key]);

                    // Fallback to this when the client IP falls into the range of trusted proxies
                    if (null === $firstTrustedIp) {
                        $firstTrustedIp = $clientIp;
                    }
                }
            }

            // Now the IP chain contains only untrusted proxies and the client IP
            return $clientIps ? array_reverse($clientIps) : array($firstTrustedIp);
        }
    }