diff --git a/build/psalm-baseline.xml b/build/psalm-baseline.xml
index a8c6a2e1a33ff..ef8d61bcd8855 100644
--- a/build/psalm-baseline.xml
+++ b/build/psalm-baseline.xml
@@ -3337,9 +3337,6 @@
getOverwriteHost()]]>
- cookies[$key]) ? $this->cookies[$key] : null]]>
- env[$key]) ? $this->env[$key] : null]]>
- files[$key]) ? $this->files[$key] : null]]>
diff --git a/lib/private/AppFramework/Http/Request.php b/lib/private/AppFramework/Http/Request.php
index e02f20ca308c5..a41b6fb57938a 100644
--- a/lib/private/AppFramework/Http/Request.php
+++ b/lib/private/AppFramework/Http/Request.php
@@ -20,16 +20,20 @@
use Symfony\Component\HttpFoundation\IpUtils;
/**
- * Class for accessing variables in the request.
- * This class provides an immutable object with request variables.
+ * Default immutable IRequest implementation.
*
- * @property mixed[] $cookies
- * @property mixed[] $env
- * @property mixed[] $files
- * @property string $method
- * @property mixed[] $parameters
- * @property mixed[] $server
- * @template-implements \ArrayAccess
+ * @property-read array $get
+ * @property-read array $post
+ * @property-read array|resource $put
+ * @property-read array $patch
+ * @property-read string $method
+ * @property-read array $server
+ * @property-read array $urlParams
+ * @property-read array $cookies
+ * @property-read array $env
+ * @property-read array $files
+ * @property-read array $parameters
+ * @template-implements \ArrayAccess
*/
class Request implements \ArrayAccess, \Countable, IRequest {
public const USER_AGENT_IE = '/(MSIE)|(Trident)/';
@@ -45,9 +49,24 @@ class Request implements \ArrayAccess, \Countable, IRequest {
// Android Chrome user agent: https://developers.google.com/chrome/mobile/docs/user-agent
public const USER_AGENT_ANDROID_MOBILE_CHROME = '#Android.*Chrome/[.0-9]*#';
public const USER_AGENT_FREEBOX = '#^Mozilla/5\.0$#';
+
public const REGEX_LOCALHOST = '/^(127\.0\.0\.1|localhost|\[::1\])$/';
+
+ /**
+ * Whether the raw PUT body stream has already been returned.
+ */
private bool $isPutStreamContentAlreadySent = false;
+
+ /**
+ * Internal request data store.
+ */
protected array $items = [];
+
+ /**
+ * Magic properties that are exposed directly from $items.
+ *
+ * @var list
+ */
protected array $allowedKeys = [
'get',
'post',
@@ -61,24 +80,27 @@ class Request implements \ArrayAccess, \Countable, IRequest {
'requesttoken',
];
+ /**
+ * Whether request-body decoding has already been attempted.
+ */
protected bool $contentDecoded = false;
+
+ /**
+ * Deferred decoding error from the request body, if any.
+ */
private ?\JsonException $decodingException = null;
/**
- * @param array $vars An associative array with the following optional values:
- * - array 'urlParams' the parameters which were matched from the URL
+ * @param array $vars Associative request data with the following optional keys:
+ * - array 'urlParams' route parameters extracted from the URL
* - array 'get' the $_GET array
- * - array|string 'post' the $_POST array or JSON string
+ * - array 'post' the $_POST array
* - array 'files' the $_FILES array
* - array 'server' the $_SERVER array
* - array 'env' the $_ENV array
* - array 'cookies' the $_COOKIE array
- * - string 'method' the request method (GET, POST etc)
- * - string|false 'requesttoken' the requesttoken or false when not available
- * @param IRequestId $requestId
- * @param IConfig $config
- * @param CsrfTokenManager|null $csrfTokenManager
- * @param string $inputStream
+ * - string 'method' the HTTP request method, for example GET or POST
+ * - string|false 'requesttoken' the request token, or false if unavailable
* @see https://www.php.net/manual/en/reserved.variables.php
*/
public function __construct(
@@ -105,8 +127,16 @@ public function __construct(
$this->items['params']
);
}
+
/**
+ * Replaces the current URL parameters and merges them into the parameter set.
+ *
+ * URL parameters take precedence over previously merged values with the same
+ * key.
+ *
* @param array $parameters
+ *
+ * @internal public only so it can be consumed by OC\AppFramework\App
*/
public function setUrlParameters(array $parameters) {
$this->items['urlParams'] = $parameters;
@@ -117,8 +147,7 @@ public function setUrlParameters(array $parameters) {
}
/**
- * Countable method
- * @return int
+ * Returns the number of merged request parameters.
*/
#[\Override]
public function count(): int {
@@ -126,24 +155,12 @@ public function count(): int {
}
/**
- * ArrayAccess methods
+ * Whether a merged request parameter exists.
*
- * Gives access to the combined GET, POST and urlParams arrays
+ * ArrayAccess operates on the merged parameter set.
*
- * Examples:
- *
- * $var = $request['myvar'];
- *
- * or
- *
- * if(!isset($request['myvar']) {
- * // Do something
- * }
- *
- * $request['myvar'] = 'something'; // This throws an exception.
- *
- * @param string $offset The key to lookup
- * @return boolean
+ * @param string $offset Parameter name
+ * @return bool
*/
#[\Override]
public function offsetExists($offset): bool {
@@ -151,8 +168,9 @@ public function offsetExists($offset): bool {
}
/**
- * @see offsetExists
- * @param string $offset
+ * Returns a merged request parameter value, or null if it is missing.
+ *
+ * @param string $offset Parameter name
* @return mixed
*/
#[\Override]
@@ -162,7 +180,8 @@ public function offsetGet($offset) {
}
/**
- * @see offsetExists
+ * Request objects are immutable.
+ *
* @param string $offset
* @param mixed $value
*/
@@ -172,7 +191,8 @@ public function offsetSet($offset, $value): void {
}
/**
- * @see offsetExists
+ * Request objects are immutable.
+ *
* @param string $offset
*/
#[\Override]
@@ -181,7 +201,8 @@ public function offsetUnset($offset): void {
}
/**
- * Magic property accessors
+ * Request objects are immutable.
+ *
* @param string $name
* @param mixed $value
*/
@@ -190,17 +211,16 @@ public function __set($name, $value) {
}
/**
- * Access request variables by method and name.
- * Examples:
+ * Returns request data through magic property access.
*
- * $request->post['myvar']; // Only look for POST variables
- * $request->myvar; or $request->{'myvar'}; or $request->{$myvar}
- * Looks in the combined GET, POST and urlParams array.
+ * Named properties read from the merged parameter set. Method-specific
+ * properties (`get`, `post`, `put`, `patch`) are only available for the
+ * matching HTTP method and throw a \LogicException otherwise.
*
- * If you access e.g. ->post but the current HTTP request method
- * is GET a \LogicException will be thrown.
+ * Depending on the method and content type, `put` may return either parsed
+ * parameters or a readable stream for the raw request body.
*
- * @param string $name The key to look for.
+ * @param string $name Property name
* @throws \LogicException
* @return mixed|null
*/
@@ -235,6 +255,8 @@ public function __get($name) {
}
/**
+ * Whether a magic property is available.
+ *
* @param string $name
* @return bool
*/
@@ -246,55 +268,38 @@ public function __isset($name) {
}
/**
+ * Request objects are immutable.
+ *
* @param string $id
*/
public function __unset($id) {
throw new \RuntimeException('You cannot change the contents of the request object');
}
- /**
- * Returns the value for a specific http header.
- *
- * This method returns an empty string if the header did not exist.
- *
- * @param string $name
- * @return string
- */
#[\Override]
public function getHeader(string $name): string {
- $name = strtoupper(str_replace('-', '_', $name));
- if (isset($this->server['HTTP_' . $name])) {
- return $this->server['HTTP_' . $name];
+ $elementName = strtoupper(str_replace('-', '_', $name));
+
+ // Check if standard HTTP header
+ $clientHeaderKey = 'HTTP_' . $elementName;
+ if (isset($this->server[$clientHeaderKey])) {
+ return $this->server[$clientHeaderKey];
}
- // There's a few headers that seem to end up in the top-level
- // server array.
- switch ($name) {
- case 'CONTENT_TYPE':
- case 'CONTENT_LENGTH':
- case 'REMOTE_ADDR':
- if (isset($this->server[$name])) {
- return $this->server[$name];
- }
- break;
+ // Check if special request-related element
+ $specialKeys = [
+ 'CONTENT_TYPE' => true,
+ 'CONTENT_LENGTH' => true,
+ 'REMOTE_ADDR' => true,
+ ];
+
+ if (isset($specialKeys[$elementName]) && isset($this->server[$elementName])) {
+ return $this->server[$elementName];
}
return '';
}
- /**
- * Lets you access post and get parameters by the index
- * In case of json requests the encoded json body is accessed
- *
- * @param string $key the key which you want to access in the URL Parameter
- * placeholder, $_POST or $_GET array.
- * The priority how they're returned is the following:
- * 1. URL parameters
- * 2. POST parameters
- * 3. GET parameters
- * @param mixed $default If the key is not found, this value will be returned
- * @return mixed the content of the array
- */
#[\Override]
public function getParam(string $key, $default = null) {
return isset($this->parameters[$key])
@@ -302,68 +307,43 @@ public function getParam(string $key, $default = null) {
: $default;
}
- /**
- * Returns all params that were received, be it from the request
- * (as GET or POST) or through the URL by the route
- * @return array the array with all parameters
- */
#[\Override]
public function getParams(): array {
return is_array($this->parameters) ? $this->parameters : [];
}
- /**
- * Returns the method of the request
- * @return string the method of the request (POST, GET, etc)
- */
#[\Override]
public function getMethod(): string {
return $this->method;
}
- /**
- * Shortcut for accessing an uploaded file through the $_FILES array
- * @param string $key the key that will be taken from the $_FILES array
- * @return array the file in the $_FILES element
- */
#[\Override]
public function getUploadedFile(string $key) {
return isset($this->files[$key]) ? $this->files[$key] : null;
}
- /**
- * Shortcut for getting env variables
- * @param string $key the key that will be taken from the $_ENV array
- * @return array the value in the $_ENV element
- */
#[\Override]
public function getEnv(string $key) {
return isset($this->env[$key]) ? $this->env[$key] : null;
}
- /**
- * Shortcut for getting cookie variables
- * @param string $key the key that will be taken from the $_COOKIE array
- * @return string the value in the $_COOKIE element
- */
#[\Override]
public function getCookie(string $key) {
return isset($this->cookies[$key]) ? $this->cookies[$key] : null;
}
/**
- * Returns the request body content.
+ * Returns request body content for method-specific magic accessors.
*
- * If the HTTP request method is PUT and the body
- * not application/x-www-form-urlencoded or application/json a stream
- * resource is returned, otherwise an array.
- *
- * @return array|string|resource The request body content or a resource to read the body stream.
+ * For PUT requests with a non-empty body that is neither JSON nor
+ * form-encoded, a readable stream resource for the raw body is returned.
+ * Otherwise, parsed parameters are returned as an array.
*
+ * @return array|string|resource The request body content or a resource for the raw body stream
* @throws \LogicException
*/
protected function getContent() {
- // If the content can't be parsed into an array then return a stream resource.
+ // If the content cannot be parsed into parameters, return a raw body stream.
if ($this->isPutStreamContent()) {
if ($this->isPutStreamContentAlreadySent) {
throw new \LogicException(
@@ -388,7 +368,13 @@ private function isPutStreamContent(): bool {
}
/**
- * Attempt to decode the content and populate parameters
+ * Decodes the request body, if applicable, and merges decoded parameters
+ * into the parameter set.
+ *
+ * JSON-compatible content types are decoded from the input stream. For
+ * non-GET and non-POST form-encoded requests, the input stream is parsed
+ * into parameters. Decoding errors are stored and can later be rethrown via
+ * throwDecodingExceptionIfAny().
*/
protected function decodeContent() {
if ($this->contentDecoded) {
@@ -396,7 +382,7 @@ protected function decodeContent() {
}
$params = [];
- // 'application/json' and other JSON-related content types must be decoded manually.
+ // JSON-compatible content types must be decoded manually.
if (preg_match(self::JSON_CONTENT_TYPE_REGEX, $this->getHeader('Content-Type')) === 1) {
$content = file_get_contents($this->inputStream);
if ($content !== '') {
@@ -412,8 +398,7 @@ protected function decodeContent() {
$this->items['post'] = $params;
}
}
- // Handle application/x-www-form-urlencoded for methods other than GET
- // or post correctly
+ // Handle form-encoded request bodies for methods other than GET and POST.
} elseif ($this->method !== 'GET'
&& $this->method !== 'POST'
&& str_contains($this->getHeader('Content-Type'), 'application/x-www-form-urlencoded')) {
@@ -436,10 +421,6 @@ public function throwDecodingExceptionIfAny(): void {
}
}
- /**
- * Checks if the CSRF check was correct
- * @return bool true if CSRF check passed
- */
#[\Override]
public function passesCSRFCheck(): bool {
if ($this->csrfTokenManager === null) {
@@ -470,9 +451,7 @@ public function passesCSRFCheck(): bool {
}
/**
- * Whether the cookie checks are required
- *
- * @return bool
+ * Whether cookie-based same-site checks are required for this request.
*/
private function cookieCheckRequired(): bool {
if ($this->getHeader('OCS-APIREQUEST')) {
@@ -486,19 +465,14 @@ private function cookieCheckRequired(): bool {
}
/**
- * Wrapper around session_get_cookie_params
- *
- * @return array
+ * Wrapper around session_get_cookie_params().
*/
public function getCookieParams(): array {
return session_get_cookie_params();
}
/**
- * Appends the __Host- prefix to the cookie if applicable
- *
- * @param string $name
- * @return string
+ * Returns the cookie name with the __Host- prefix applied when appropriate.
*/
protected function getProtectedCookieName(string $name): string {
$cookieParams = $this->getCookieParams();
@@ -510,13 +484,6 @@ protected function getProtectedCookieName(string $name): string {
return $prefix . $name;
}
- /**
- * Checks if the strict cookie has been sent with the request if the request
- * is including any cookies.
- *
- * @return bool
- * @since 9.1.0
- */
#[\Override]
public function passesStrictCookieCheck(): bool {
if (!$this->cookieCheckRequired()) {
@@ -531,13 +498,6 @@ public function passesStrictCookieCheck(): bool {
return false;
}
- /**
- * Checks if the lax cookie has been sent with the request if the request
- * is including any cookies.
- *
- * @return bool
- * @since 9.1.0
- */
#[\Override]
public function passesLaxCookieCheck(): bool {
if (!$this->cookieCheckRequired()) {
@@ -551,39 +511,30 @@ public function passesLaxCookieCheck(): bool {
return false;
}
- /**
- * Returns an ID for the request, value is not guaranteed to be unique and is mostly meant for logging
- * If `mod_unique_id` is installed this value will be taken.
- * @return string
- */
#[\Override]
public function getId(): string {
return $this->requestId->getId();
}
/**
- * Checks if given $remoteAddress matches any entry in the given array $trustedProxies.
- * For details regarding what "match" means, refer to `matchesTrustedProxy`.
- * @return boolean true if $remoteAddress matches any entry in $trustedProxies, false otherwise
+ * Checks whether the given remote address matches one of the configured
+ * trusted proxies.
+ *
+ * Invalid trusted proxy configuration is treated as non-matching.
+ *
+ * @return bool true if $remoteAddress matches a trusted proxy, false otherwise
*/
protected function isTrustedProxy($trustedProxies, $remoteAddress) {
try {
return IpUtils::checkIp($remoteAddress, $trustedProxies);
} catch (\Throwable) {
- // We can not log to our log here as the logger is using `getRemoteAddress` which uses the function, so we would have a cyclic dependency
- // Reaching this line means `trustedProxies` is in invalid format.
+ // Cannot log through the regular logger here because it may depend on
+ // getRemoteAddress(), which would create a cyclic dependency.
error_log('Nextcloud trustedProxies has malformed entries');
return false;
}
}
- /**
- * Returns the remote address, if the connection came from a trusted proxy
- * and `forwarded_for_headers` has been configured then the IP address
- * specified in this header will be returned instead.
- * Do always use this instead of $_SERVER['REMOTE_ADDR']
- * @return string IP address
- */
#[\Override]
public function getRemoteAddress(): string {
$remoteAddress = isset($this->server['REMOTE_ADDR']) ? $this->server['REMOTE_ADDR'] : '';
@@ -627,26 +578,12 @@ public function getRemoteAddress(): string {
return $remoteAddress;
}
- /**
- * Check overwrite condition
- * @return bool
- */
private function isOverwriteCondition(): bool {
$regex = '/' . $this->config->getSystemValueString('overwritecondaddr', '') . '/';
$remoteAddr = isset($this->server['REMOTE_ADDR']) ? $this->server['REMOTE_ADDR'] : '';
return $regex === '//' || preg_match($regex, $remoteAddr) === 1;
}
- /**
- * Returns the server protocol. It respects one or more reverse proxies servers
- * and load balancers. Precedence:
- * 1. `overwriteprotocol` config value
- * 2. `X-Forwarded-Proto` header value
- * 3. $_SERVER['HTTPS'] value
- * If an invalid protocol is provided, defaults to http, continues, but logs as an error.
- *
- * @return string Server protocol (http or https)
- */
#[\Override]
public function getServerProtocol(): string {
$proto = 'http';
@@ -682,11 +619,6 @@ public function getServerProtocol(): string {
return $proto === 'https' ? 'https' : 'http';
}
- /**
- * Returns the used HTTP protocol.
- *
- * @return string HTTP protocol. HTTP/2, HTTP/1.1 or HTTP/1.0.
- */
#[\Override]
public function getHttpProtocol(): string {
$claimedProtocol = $this->server['SERVER_PROTOCOL'] ?? '';
@@ -708,11 +640,6 @@ public function getHttpProtocol(): string {
return 'HTTP/1.1';
}
- /**
- * Returns the request uri, even if the website uses one or more
- * reverse proxies
- * @return string
- */
#[\Override]
public function getRequestUri(): string {
$uri = isset($this->server['REQUEST_URI']) ? $this->server['REQUEST_URI'] : '';
@@ -722,11 +649,6 @@ public function getRequestUri(): string {
return $uri;
}
- /**
- * Get raw PathInfo from request (not urldecoded)
- * @throws \Exception
- * @return string Path info
- */
#[\Override]
public function getRawPathInfo(): string {
$requestUri = isset($this->server['REQUEST_URI']) ? $this->server['REQUEST_URI'] : '';
@@ -768,22 +690,12 @@ public function getRawPathInfo(): string {
}
}
- /**
- * Get PathInfo from request (rawurldecoded)
- * @throws \Exception
- * @return string|false Path info or false when not found
- */
#[\Override]
public function getPathInfo(): string|false {
$pathInfo = $this->getRawPathInfo();
return \Sabre\HTTP\decodePath($pathInfo);
}
- /**
- * Returns the script name, even if the website uses one or more
- * reverse proxies
- * @return string the script name
- */
#[\Override]
public function getScriptName(): string {
$name = $this->server['SCRIPT_NAME'] ?? '';
@@ -797,11 +709,6 @@ public function getScriptName(): string {
return $name;
}
- /**
- * Checks whether the user agent matches a given regex
- * @param array $agent array of agent names
- * @return bool true if at least one of the given agent matches, false otherwise
- */
#[\Override]
public function isUserAgent(array $agent): bool {
if (!isset($this->server['HTTP_USER_AGENT'])) {
@@ -815,11 +722,6 @@ public function isUserAgent(array $agent): bool {
return false;
}
- /**
- * Returns the unverified server host from the headers without checking
- * whether it is a trusted domain
- * @return string Server host
- */
#[\Override]
public function getInsecureServerHost(): string {
if ($this->fromTrustedProxy() && $this->getOverwriteHost() !== null) {
@@ -845,11 +747,6 @@ public function getInsecureServerHost(): string {
return $host;
}
- /**
- * Returns the server host from the headers, or the first configured
- * trusted domain if the host isn't in the trusted list
- * @return string Server host
- */
#[\Override]
public function getServerHost(): string {
// overwritehost is always trusted
@@ -878,10 +775,9 @@ public function getServerHost(): string {
}
/**
- * Returns the overwritehost setting from the config if set and
- * if the overwrite condition is met
- * @return string|null overwritehost value or null if not defined or the defined condition
- * isn't met
+ * Returns the overwritehost config value if configured and applicable.
+ *
+ * @return string|null
*/
private function getOverwriteHost() {
if ($this->config->getSystemValueString('overwritehost') !== '' && $this->isOverwriteCondition()) {
diff --git a/lib/private/AppFramework/Http/RequestId.php b/lib/private/AppFramework/Http/RequestId.php
index ba4982895906d..d63f5e63c7ad6 100644
--- a/lib/private/AppFramework/Http/RequestId.php
+++ b/lib/private/AppFramework/Http/RequestId.php
@@ -18,11 +18,6 @@ public function __construct(
) {
}
- /**
- * Returns an ID for the request, value is not guaranteed to be unique and is mostly meant for logging
- * If `mod_unique_id` is installed this value will be taken.
- * @return string
- */
#[\Override]
public function getId(): string {
if (empty($this->requestId)) {
diff --git a/lib/public/IRequest.php b/lib/public/IRequest.php
index 1ca66c646e830..2510c48834d4b 100644
--- a/lib/public/IRequest.php
+++ b/lib/public/IRequest.php
@@ -6,35 +6,40 @@
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
* SPDX-License-Identifier: AGPL-3.0-only
*/
-// use OCP namespace for all classes that are considered public.
-// This means that they should be used by apps instead of the internal Nextcloud classes
namespace OCP;
/**
- * This interface provides an immutable object with with accessors to
- * request variables and headers.
+ * Immutable request wrapper with accessors for request variables and other
+ * request-related data.
*
- * Access request variables by method and name.
+ * Request data should be retrieved through this interface whenever possible.
*
- * Examples:
+ * Parameters can be accessed through dedicated methods or via magic property
+ * access, for example:
*
- * $request->post['myvar']; // Only look for POST variables
- * $request->myvar; or $request->{'myvar'}; or $request->{$myvar}
- * Looks in the combined GET, POST and urlParams array.
+ * $request->post['myvar']; // POST body parameters on POST requests
+ * $request->myvar; // merged request parameters
*
- * If you access e.g. ->post but the current HTTP request method
- * is GET a \LogicException will be thrown.
+ * Magic access to a named parameter reads from the merged request parameter
+ * set. Method-specific properties such as `get`, `post`, `put`, and `patch`
+ * are only available for the matching HTTP method and may throw a
+ * \LogicException otherwise.
*
- * NOTE:
- * - When accessing ->put a stream resource is returned and the accessor
- * will return false on subsequent access to ->put or ->patch.
- * - When accessing ->patch and the Content-Type is either application/json
- * or application/x-www-form-urlencoded (most cases) it will act like ->get
- * and ->post and return an array. Otherwise the raw data will be returned.
+ * In PUT requests, if the body is JSON or form-encoded, `->put` behaves like
+ * the other method-specific accessors and returns parsed request parameters.
+ * Otherwise, for non-empty request bodies, it returns a readable stream
+ * resource for the raw request body. Such streamed PUT bodies can only be
+ * accessed once; repeated access throws a \LogicException.
*
- * @property-read string[] $server
+ * @property-read array $get
+ * @property-read array $post
+ * @property-read array|resource $put
+ * @property-read array $patch
+ * @property-read string $method
+ * @property-read array $server
* @property-read string[] $urlParams
+ *
* @since 6.0.0
*/
interface IRequest {
@@ -92,111 +97,121 @@ interface IRequest {
public const JSON_CONTENT_TYPE_REGEX = '/^application\/(?:[a-z0-9.-]+\+)?json\b/';
/**
- * @param string $name
+ * Returns the value of a request header, or an empty string if missing.
+ *
+ * Header names are matched case-insensitively.
+ *
+ * Besides normal HTTP headers, also supports selected request-related
+ * server values such as `REMOTE_ADDR`.
*
* @psalm-taint-source input
*
- * @return string
* @since 6.0.0
*/
public function getHeader(string $name): string;
/**
- * Lets you access post and get parameters by the index
- * In case of json requests the encoded json body is accessed
+ * Returns a parameter value from the merged parameter set.
+ *
+ * The merged parameter set is primarily composed from route URL parameters,
+ * POST parameters and GET parameters. Depending on request content type and
+ * prior access, lazily decoded request-body parameters may also be present.
*
* @psalm-taint-source input
*
- * @param string $key the key which you want to access in the URL Parameter
- * placeholder, $_POST or $_GET array.
- * The priority how they're returned is the following:
- * 1. URL parameters
- * 2. POST parameters
- * 3. GET parameters
- * @param mixed $default If the key is not found, this value will be returned
- * @return mixed the content of the array
+ * @param string $key the key to look up
+ * @param mixed $default the value to return if the key is not found
+ * @return mixed the parameter value, or $default if the key is not present
* @since 6.0.0
*/
public function getParam(string $key, $default = null);
/**
- * Returns all params that were received, be it from the request
+ * Returns the merged parameter set currently available on the request.
*
- * (as GET or POST) or through the URL by the route
+ * This includes request parameters from GET, POST and route URL parameters,
+ * and may also include decoded request-body parameters.
*
* @psalm-taint-source input
*
- * @return array the array with all parameters
+ * @return array the merged parameters
* @since 6.0.0
*/
public function getParams(): array;
/**
- * Returns the method of the request
+ * Returns the request method.
*
- * @return string the method of the request (POST, GET, etc)
+ * @return string the HTTP method, for example GET, POST, PUT, or PATCH
* @since 6.0.0
*/
public function getMethod(): string;
/**
- * Shortcut for accessing an uploaded file through the $_FILES array
+ * Returns an uploaded file entry from the `$_FILES` data, if present.
*
- * @param string $key the key that will be taken from the $_FILES array
- * @return array the file in the $_FILES element
+ * @param string $key the file field name
+ * @return array|null the matching uploaded file entry, or null if missing
* @since 6.0.0
*/
public function getUploadedFile(string $key);
/**
- * Shortcut for getting env variables
+ * Returns an environment value from the request environment, if present.
*
- * @param string $key the key that will be taken from the $_ENV array
- * @return array the value in the $_ENV element
+ * @param string $key the environment variable name
+ * @return mixed|null the environment value, or null if missing
* @since 6.0.0
*/
public function getEnv(string $key);
/**
- * Shortcut for getting cookie variables
+ * Returns a cookie value, if present.
*
* @psalm-taint-source input
*
- * @param string $key the key that will be taken from the $_COOKIE array
- * @return string|null the value in the $_COOKIE element
+ * @param string $key the cookie name
+ * @return string|null the cookie value, or null if missing
* @since 6.0.0
*/
public function getCookie(string $key);
/**
- * Checks if the CSRF check was correct
+ * Checks whether the request passes CSRF validation.
+ *
+ * Depending on the request, this may include same-site cookie checks and
+ * token validation from request parameters or headers. OCS API requests are
+ * handled specially by the implementation (if the OCS-APIRequest header is
+ * included in the request).
*
- * @return bool true if CSRF check passed
+ * @return bool true if the request passes CSRF validation
* @since 6.0.0
*/
public function passesCSRFCheck(): bool;
/**
- * Checks if the strict cookie has been sent with the request if the request
- * is including any cookies.
+ * Checks whether the strict same-site cookie requirement is satisfied when
+ * session or authentication cookies are part of the request.
*
- * @return bool
+ * @return bool true if the strict cookie check passes
* @since 9.0.0
*/
public function passesStrictCookieCheck(): bool;
/**
- * Checks if the lax cookie has been sent with the request if the request
- * is including any cookies.
+ * Checks whether the lax same-site cookie requirement is satisfied when
+ * session or authentication cookies are part of the request.
*
- * @return bool
+ * @return bool true if the lax cookie check passes
* @since 9.0.0
*/
public function passesLaxCookieCheck(): bool;
/**
- * Returns an ID for the request, value is not guaranteed to be unique and is mostly meant for logging
- * If `mod_unique_id` is installed this value will be taken.
+ * Returns a request identifier intended primarily for logging and tracing.
+ *
+ * The value is not guaranteed to be globally unique. If `mod_unique_id` is
+ * installed, that value may be used by the implementation.
*
* @return string
* @since 8.1.0
@@ -204,10 +219,14 @@ public function passesLaxCookieCheck(): bool;
public function getId(): string;
/**
- * Returns the remote address, if the connection came from a trusted proxy
- * and `forwarded_for_headers` has been configured then the IP address
- * specified in this header will be returned instead.
- * Do always use this instead of $_SERVER['REMOTE_ADDR']
+ * Returns the effective remote IP address.
+ *
+ * If the connection comes from a trusted proxy and `forwarded_for_headers`
+ * is configured, the client IP from those forwarded headers is used
+ * instead.
+ *
+ * Do not use `$_SERVER['REMOTE_ADDR']` directly when this method is
+ * available.
*
* @return string IP address
* @since 8.1.0
@@ -215,25 +234,31 @@ public function getId(): string;
public function getRemoteAddress(): string;
/**
- * Returns the server protocol. It respects reverse proxy servers and load
- * balancers.
+ * Returns the effective server protocol.
+ *
+ * Respects reverse proxies and load balancers. Precedence:
+ * 1. `overwriteprotocol` config value
+ * 2. `X-Forwarded-Proto` header value
+ * 3. `$_SERVER['HTTPS']` value
+ *
+ * Invalid values fall back to `http`.
*
- * @return string Server protocol (http or https)
+ * @return string Server protocol: `http` or `https`
* @since 8.1.0
*/
public function getServerProtocol(): string;
/**
- * Returns the used HTTP protocol.
+ * Returns the HTTP protocol version used for the request.
*
- * @return string HTTP protocol. HTTP/2, HTTP/1.1 or HTTP/1.0.
+ * @return string HTTP protocol, for example HTTP/2, HTTP/1.1, or HTTP/1.0
* @since 8.2.0
*/
public function getHttpProtocol(): string;
/**
- * Returns the request uri, even if the website uses one or more
- * reverse proxies
+ * Returns the request URI, taking reverse-proxy and overwrite settings into
+ * account.
*
* @psalm-taint-source input
*
@@ -243,30 +268,30 @@ public function getHttpProtocol(): string;
public function getRequestUri(): string;
/**
- * Get raw PathInfo from request (not urldecoded)
+ * Returns raw path info from the request without URL decoding.
*
* @psalm-taint-source input
*
* @throws \Exception
- * @return string Path info
+ * @return string path info
* @since 8.1.0
*/
public function getRawPathInfo(): string;
/**
- * Get PathInfo from request
+ * Returns decoded path info from the request.
*
* @psalm-taint-source input
*
* @throws \Exception
- * @return string|false Path info or false when not found
+ * @return string|false path info, or false when it cannot be determined
* @since 8.1.0
*/
public function getPathInfo();
/**
- * Returns the script name, even if the website uses one or more
- * reverse proxies
+ * Returns the effective script name, taking reverse-proxy and overwrite
+ * settings into account.
*
* @return string the script name
* @since 8.1.0
@@ -274,38 +299,46 @@ public function getPathInfo();
public function getScriptName(): string;
/**
- * Checks whether the user agent matches a given regex
+ * Checks whether the current user agent matches at least one of the given
+ * regular expressions.
*
- * @param array $agent array of agent names
- * @return bool true if at least one of the given agent matches, false otherwise
+ * @param array $agent array of user-agent regex patterns
+ * @return bool true if at least one pattern matches, false otherwise
* @since 8.1.0
*/
public function isUserAgent(array $agent): bool;
/**
- * Returns the unverified server host from the headers without checking
- * whether it is a trusted domain
+ * Returns the effective host value without validating it against the trusted
+ * domains configuration.
+ *
+ * This may be derived from request headers, proxy headers, or server
+ * variables, depending on the deployment setup.
*
* @psalm-taint-source input
*
- * @return string Server host
+ * @return string server host
* @since 8.1.0
*/
public function getInsecureServerHost(): string;
/**
- * Returns the server host from the headers, or the first configured
- * trusted domain if the host isn't in the trusted list
+ * Returns the validated effective server host.
+ *
+ * The implementation may use overwrite host configuration first. Otherwise
+ * it derives the host from the request and returns it only if it is trusted;
+ * if not, it falls back to the first configured trusted domain.
*
- * @return string Server host
+ * @return string server host
* @since 8.1.0
*/
public function getServerHost(): string;
/**
- * If decoding the request content failed, throw an exception.
- * Currently only \JsonException for json decoding errors,
- * but in the future may throw other exceptions for other decoding issues.
+ * Throws any stored request-content decoding exception.
+ *
+ * Currently this is used for JSON decoding errors, but implementations may
+ * throw other decoding-related exceptions in the future.
*
* @throws \Exception
* @since 32.0.0
@@ -313,9 +346,10 @@ public function getServerHost(): string;
public function throwDecodingExceptionIfAny(): void;
/**
- * Returns the format of the response to this request.
+ * Returns the requested response format, if it can be determined.
*
- * The `Accept` header and the `format` query parameter control the format.
+ * The `format` request parameter takes precedence. Otherwise the format may
+ * be inferred from the `Accept` header.
*
* @return string|null
* @since 33.0.0
diff --git a/lib/public/IRequestId.php b/lib/public/IRequestId.php
index fdbebfe2fc7f7..828568bf8238a 100644
--- a/lib/public/IRequestId.php
+++ b/lib/public/IRequestId.php
@@ -12,9 +12,12 @@
* @since 24.0.0
*/
interface IRequestId {
+
/**
- * Returns an ID for the request, value is not guaranteed to be unique and is mostly meant for logging
- * If `mod_unique_id` is installed this value will be taken.
+ * Returns a request identifier intended primarily for logging and tracing.
+ *
+ * The value is not guaranteed to be globally unique. If `mod_unique_id` is
+ * installed, that value may be used by the implementation.
*
* @return string
* @since 24.0.0