diff --git a/.github/workflows/php83.yaml b/.github/workflows/php83.yaml
index 8ecb8080..56bbbd11 100644
--- a/.github/workflows/php83.yaml
+++ b/.github/workflows/php83.yaml
@@ -32,8 +32,6 @@ jobs:
name: Code Quality
needs: test
uses: WebFiori/workflows/.github/workflows/quality-sonarcloud.yaml@main
- with:
- coverage-file: 'php-8.3-coverage.xml'
secrets:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
diff --git a/.gitignore b/.gitignore
index 594e91d1..7742743f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,3 +13,5 @@ php-cs-fixer-v2.phar
php-cs-fixer.phar
.php-cs-fixer.cache
*.Identifier
+/tests/.phpunit.cache
+/.vscode
diff --git a/WebFiori/Http/APIFilter.php b/WebFiori/Http/APIFilter.php
index 67e63f05..ea9551a1 100644
--- a/WebFiori/Http/APIFilter.php
+++ b/WebFiori/Http/APIFilter.php
@@ -2,7 +2,7 @@
/**
* This file is licensed under MIT License.
*
- * Copyright (c) 2019 Ibrahim BinAlshikh
+ * Copyright (c) 2019 WebFiori Framework
*
* For more information on the license, please visit:
* https://github.com/WebFiori/http/blob/master/LICENSE
diff --git a/WebFiori/Http/APITestCase.php b/WebFiori/Http/APITestCase.php
index 77bcfc5e..30c92089 100644
--- a/WebFiori/Http/APITestCase.php
+++ b/WebFiori/Http/APITestCase.php
@@ -2,7 +2,7 @@
/**
* This file is licensed under MIT License.
*
- * Copyright (c) 2024 Ibrahim BinAlshikh
+ * Copyright (c) 2019 WebFiori Framework
*
* For more information on the license, please visit:
* https://github.com/WebFiori/http/blob/master/LICENSE
@@ -294,6 +294,7 @@ private function unset(array &$arr, array $params, WebServicesManager $m, array
$_SERVER['HTTP_'.strtoupper($trHeader)] = $trVal;
}
}
+ $m->setRequest(Request::createFromGlobals());
$m->process();
foreach ($params as $key => $val) {
diff --git a/WebFiori/Http/AbstractWebService.php b/WebFiori/Http/AbstractWebService.php
index 25eae1fb..f6b97bb3 100644
--- a/WebFiori/Http/AbstractWebService.php
+++ b/WebFiori/Http/AbstractWebService.php
@@ -2,7 +2,7 @@
/**
* This file is licensed under MIT License.
*
- * Copyright (c) 2019 Ibrahim BinAlshikh
+ * Copyright (c) 2019 WebFiori Framework
*
* For more information on the license, please visit:
* https://github.com/WebFiori/http/blob/master/LICENSE
@@ -36,7 +36,12 @@ abstract class AbstractWebService implements JsonI {
*
*/
const I = 'info';
-
+ /**
+ * A constant which is used to indicate that the message that will be
+ * sent is of type success.
+ *
+ */
+ const S = 'success';
/**
* The name of the service.
*
@@ -65,6 +70,13 @@ abstract class AbstractWebService implements JsonI {
*
*/
private $reqMethods;
+ /**
+ * The request instance used by the service.
+ *
+ * @var Request
+ *
+ */
+ private $request;
/**
* This is used to indicate if authentication is required when the service
* is called.
@@ -123,6 +135,7 @@ public function __construct(string $name) {
$this->requireAuth = true;
$this->sinceVersion = '1.0.0';
$this->serviceDesc = '';
+ $this->request = Request::createFromGlobals();
}
/**
* Returns an array that contains all possible requests methods at which the
@@ -326,10 +339,21 @@ public final function addResponseDescription(string $description) {
* ('basic', 'bearer', 'digest', etc...). The 'credentials' will contain
* the credentials which can be used to authenticate the client.
*
- * @throws InvalidArgumentException
*/
public function getAuthHeader() {
- return Request::getAuthHeader();
+ if ($this->request !== null) {
+ return $this->request->getAuthHeader();
+ }
+ return null;
+ }
+
+ /**
+ * Sets the request instance for the service.
+ *
+ * @param mixed $request The request instance (Request, etc.)
+ */
+ public function setRequest($request) {
+ $this->request = $request;
}
/**
* Returns the description of the service.
@@ -690,11 +714,11 @@ public function send(string $contentType, $data, int $code = 200) {
* will be not included in response. Default is empty string. Default is null.
*
*/
- public function sendResponse(string $message, string $type = '', int $code = 200, mixed $otherInfo = '') {
+ public function sendResponse(string $message, int $code = 200, string $type = '', mixed $otherInfo = '') {
$manager = $this->getManager();
if ($manager !== null) {
- $manager->sendResponse($message, $type, $code, $otherInfo);
+ $manager->sendResponse($message, $code, $type, $otherInfo);
}
}
/**
diff --git a/WebFiori/Http/HeadersPool.php b/WebFiori/Http/HeadersPool.php
index 6e742b88..b8b6eac0 100644
--- a/WebFiori/Http/HeadersPool.php
+++ b/WebFiori/Http/HeadersPool.php
@@ -2,7 +2,7 @@
/**
* This file is licensed under MIT License.
*
- * Copyright (c) 2022 Ibrahim BinAlshikh
+ * Copyright (c) 2019 WebFiori Framework
*
* For more information on the license, please visit:
* https://github.com/WebFiori/http/blob/master/LICENSE
diff --git a/WebFiori/Http/HttpCookie.php b/WebFiori/Http/HttpCookie.php
index babfff05..53d7708a 100644
--- a/WebFiori/Http/HttpCookie.php
+++ b/WebFiori/Http/HttpCookie.php
@@ -2,7 +2,7 @@
/**
* This file is licensed under MIT License.
*
- * Copyright (c) 2022 Ibrahim BinAlshikh
+ * Copyright (c) 2019 WebFiori Framework
*
* For more information on the license, please visit:
* https://github.com/WebFiori/http/blob/master/LICENSE
@@ -57,7 +57,7 @@ class HttpCookie {
*
path: /
* secure: true
* http only: true
- * domain: The domain at which the library is operating from.
+ * domain: The domain at which the cookie is operating from.
* same site: Lax
* expires: 0
* value: sha256 hash
@@ -68,7 +68,7 @@ public function __construct() {
$this->cookieName = 'new-cookie';
$this->path = '/';
$this->secure = true;
- $this->domain = Request::getUri()->getHost();
+ $this->domain = null;
$this->sameSite = 'Lax';
$this->val = hash('sha256', date('Y-m-d H:i:s'));
$this->expires = 0;
diff --git a/WebFiori/Http/HttpHeader.php b/WebFiori/Http/HttpHeader.php
index 58dccaf8..19c38709 100644
--- a/WebFiori/Http/HttpHeader.php
+++ b/WebFiori/Http/HttpHeader.php
@@ -2,7 +2,7 @@
/**
* This file is licensed under MIT License.
*
- * Copyright (c) 2022 Ibrahim BinAlshikh
+ * Copyright (c) 2019 WebFiori Framework
*
* For more information on the license, please visit:
* https://github.com/WebFiori/http/blob/master/LICENSE
diff --git a/WebFiori/Http/HttpMessage.php b/WebFiori/Http/HttpMessage.php
new file mode 100644
index 00000000..7e9a6222
--- /dev/null
+++ b/WebFiori/Http/HttpMessage.php
@@ -0,0 +1,167 @@
+headersPool = new HeadersPool();
+ $this->body = '';
+ $this->protocolVersion = '1.1';
+ $this->requestMethod = 'GET';
+ }
+
+ /**
+ * Returns the headers pool.
+ *
+ * @return HeadersPool
+ */
+ public function getHeadersPool() : HeadersPool {
+ return $this->headersPool;
+ }
+
+ /**
+ * Returns the value(s) of specific HTTP header.
+ *
+ * @param string $name The name of the header.
+ *
+ * @return array
+ */
+ public function getHeader(string $name) : array {
+ return $this->headersPool->getHeader($name);
+ }
+
+ /**
+ * Returns an array that contains all headers.
+ *
+ * @return array
+ */
+ public function getHeaders() : array {
+ return $this->headersPool->getHeaders();
+ }
+
+ /**
+ * Checks if specific header exists.
+ *
+ * @param string $name The name of the header.
+ * @param string|null $val Optional header value to check.
+ *
+ * @return bool
+ */
+ public function hasHeader(string $name, ?string $val = '') : bool {
+ return $this->headersPool->hasHeader($name, $val);
+ }
+
+ /**
+ * Removes specific header.
+ *
+ * @param string $name The name of the header.
+ * @param string|null $val Optional header value to remove.
+ *
+ * @return bool
+ */
+ public function removeHeader(string $name, ?string $val = '') : bool {
+ return $this->headersPool->removeHeader($name, $val);
+ }
+
+ /**
+ * Adds a header to the message.
+ *
+ * @param string $name The name of the header.
+ * @param string $value The value of the header.
+ * @param string|null $replaceValue Optional value to replace.
+ *
+ * @return bool
+ */
+ public function addHeader(string $name, string $value, ?string $replaceValue = '') : bool {
+ return $this->headersPool->addHeader($name, $value, $replaceValue);
+ }
+
+ /**
+ * Gets the body of the message.
+ *
+ * @return string
+ */
+ public function getBody() : string {
+ return $this->body;
+ }
+
+ /**
+ * Sets the body of the message.
+ *
+ * @param string $body
+ */
+ public function setBody(string $body) {
+ $this->body = $body;
+ }
+
+ /**
+ * Gets the protocol version.
+ *
+ * @return string
+ */
+ public function getProtocolVersion() : string {
+ return $this->protocolVersion;
+ }
+
+ /**
+ * Sets the protocol version.
+ *
+ * @param string $version
+ */
+ public function setProtocolVersion(string $version) {
+ $this->protocolVersion = $version;
+ }
+
+ /**
+ * Gets the request method.
+ *
+ * @return string
+ */
+ public function getRequestMethod() : string {
+ return $this->requestMethod;
+ }
+
+ /**
+ * Sets the request method.
+ *
+ * @param string $method
+ */
+ public function setRequestMethod(string $method) {
+ $this->requestMethod = $method;
+ }
+}
diff --git a/WebFiori/Http/ManagerInfoService.php b/WebFiori/Http/ManagerInfoService.php
index 44c98d62..0260f240 100644
--- a/WebFiori/Http/ManagerInfoService.php
+++ b/WebFiori/Http/ManagerInfoService.php
@@ -2,7 +2,7 @@
/**
* This file is licensed under MIT License.
*
- * Copyright (c) 2020 Ibrahim BinAlshikh
+ * Copyright (c) 2019 WebFiori Framework
*
* For more information on the license, please visit:
* https://github.com/WebFiori/http/blob/master/LICENSE
diff --git a/WebFiori/Http/ObjectMapper.php b/WebFiori/Http/ObjectMapper.php
index 4f69c7e4..4ab73808 100644
--- a/WebFiori/Http/ObjectMapper.php
+++ b/WebFiori/Http/ObjectMapper.php
@@ -2,7 +2,7 @@
/**
* This file is licensed under MIT License.
*
- * Copyright (c) 2023 Ibrahim BinAlshikh
+ * Copyright (c) 2019 WebFiori Framework
*
* For more information on the license, please visit:
* https://github.com/WebFiori/.github/blob/main/LICENSE
diff --git a/WebFiori/Http/ParamOption.php b/WebFiori/Http/ParamOption.php
index e27529f4..fa53a1f7 100644
--- a/WebFiori/Http/ParamOption.php
+++ b/WebFiori/Http/ParamOption.php
@@ -2,7 +2,7 @@
/**
* This file is licensed under MIT License.
*
- * Copyright (c) 2024 Ibrahim BinAlshikh
+ * Copyright (c) 2019 WebFiori Framework
*
* For more information on the license, please visit:
* https://github.com/WebFiori/http/blob/master/LICENSE
diff --git a/WebFiori/Http/ParamType.php b/WebFiori/Http/ParamType.php
index 2b4e6843..932a4db7 100644
--- a/WebFiori/Http/ParamType.php
+++ b/WebFiori/Http/ParamType.php
@@ -2,7 +2,7 @@
/**
* This file is licensed under MIT License.
*
- * Copyright (c) 2019 Ibrahim BinAlshikh
+ * Copyright (c) 2019 WebFiori Framework
*
* For more information on the license, please visit:
* https://github.com/WebFiori/http/blob/master/LICENSE
diff --git a/WebFiori/Http/Request.php b/WebFiori/Http/Request.php
index 9b567781..3c130cea 100644
--- a/WebFiori/Http/Request.php
+++ b/WebFiori/Http/Request.php
@@ -2,7 +2,7 @@
/**
* This file is licensed under MIT License.
*
- * Copyright (c) 2019 Ibrahim BinAlshikh
+ * Copyright (c) 2024 WebFiori Framework
*
* For more information on the license, please visit:
* https://github.com/WebFiori/http/blob/master/LICENSE
@@ -12,387 +12,262 @@
use InvalidArgumentException;
/**
- * A class that represents HTTP client request.
- * The developer can use this class to access basic information about a
- * request. Note that it does not comply with PSR-7 in all aspects.
- * @author Ibrahim
+ * Modern HTTP request class that extends HttpMessage.
*
+ * @author Ibrahim
*/
-class Request {
- /**
- * An array that contains the names of request methods.
- *
- * This array contains the following strings:
- *
- * - GET
- * - HEAD
- * - POST
- * - PUT
- * - DELETE
- * - TRACE
- * - OPTIONS
- * - PATCH
- * - CONNECT
- *
- *
- * @var array An array that contains the names of request methods.
- *
- */
- const METHODS = [
- 'GET',
- 'HEAD',
- 'POST',
- 'PUT',
- 'DELETE',
- 'TRACE',
- 'OPTIONS',
- 'PATCH',
- 'CONNECT'
- ];
- /**
- *
- * @var HeadersPool
- *
- */
- private $headersPool;
- /**
- *
- * @var Response
- *
- */
- private static $inst;
+class Request extends HttpMessage {
- private function __construct() {
- $this->headersPool = new HeadersPool();
+ public function __construct() {
+ parent::__construct();
}
+
/**
- * Returns an instance of the class.
+ * Creates a Request instance from global variables.
*
* @return Request
+ */
+ public static function createFromGlobals() : Request {
+ $request = new Request();
+ $request->extractHeaders();
+ $request->setRequestMethod($request->getMethodFromGlobals());
+ $request->setBody(file_get_contents('php://input'));
+
+ return $request;
+ }
+ /**
+ * Returns an associative array of request headers.
*
+ * @return array The indices of the array will be headers names and the
+ * values are sub-arrays. Each array contains the values of the header.
*/
- public static function get() {
- if (self::$inst === null) {
- self::$inst = new Request();
+ public function getHeadersAssoc() : array {
+ $retVal = [];
+ $headers = $this->getHeaders();
+
+ foreach ($headers as $headerObj) {
+ if (!isset($retVal[$headerObj->getName()])) {
+ $retVal[$headerObj->getName()] = [];
+ }
+ $retVal[$headerObj->getName()][] = $headerObj->getValue();
}
- return self::$inst;
+ return $retVal;
}
/**
- * Returns an object that contains the value of the header 'authorization'.
- *
- * @return AuthHeader|null The object will have two primary attributes, the first is
- * the 'scheme' and the second one is 'credentials'. The 'scheme'
- * will contain the name of the scheme which is used to authenticate
- * ('basic', 'bearer', 'digest', etc...). The 'credentials' will contain
- * the credentials which can be used to authenticate the client.
+ * Returns authorization header.
*
- * @throws InvalidArgumentException
+ * @return AuthHeader|null
*/
- public static function getAuthHeader() {
- $header = self::getHeader('authorization');
-
- if (count($header) >= 1) {
+ public function getAuthHeader() {
+ $header = $this->getHeader('authorization');
+
+ if (count($header) == 1) {
return new AuthHeader($header[0]);
}
-
+
return null;
}
+
/**
- * Returns the IP address of the user who is connected to the server.
- *
- * @return string The IP address of the user who is connected to the server.
- * The value is taken from the array $_SERVER at index 'REMOTE_ADDR'.
- * If the IP address is invalid, empty string is returned.
+ * Returns the IP address of the client.
*
+ * @return string
*/
- public static function getClientIP() : string {
+ public function getClientIP() : string {
if (!isset($_SERVER['REMOTE_ADDR'])) {
return '127.0.0.1';
}
- $ip = filter_var($_SERVER['REMOTE_ADDR'],FILTER_VALIDATE_IP);
-
- if ($ip == '::1') {
+
+ $ip = $_SERVER['REMOTE_ADDR'];
+
+ if ($ip === '::1') {
return '127.0.0.1';
- } else {
- return $ip;
}
+
+ $validated = filter_var($ip, FILTER_VALIDATE_IP);
+
+ return $validated !== false ? $validated : '';
}
- /**
- * Returns request content type.
- *
- * @return string|null The value of the header 'content-type' in the request.
- *
- */
- public static function getContentType() {
- $c = isset($_SERVER['CONTENT_TYPE']) ? filter_var($_SERVER['CONTENT_TYPE']) : null;
- if ($c !== null && $c !== false) {
- return trim(explode(';', $c)[0]);
- }
-
- return null;
- }
/**
- * Returns HTTP header given its name.
- *
- * @param string $name The name of the header.
+ * Returns the content type header value.
*
- * @return array If a header which has the given name exist,
- * the method will return all header values as an array. If the header
- * does not exist, the array will be empty.
+ * @return string|null
*/
- public static function getHeader(string $name) : array {
- self::getHeaders();
-
- return self::getHeadersPool()->getHeader($name);
+ public function getContentType() {
+ return isset($_SERVER['CONTENT_TYPE']) ? filter_var($_SERVER['CONTENT_TYPE']) : null;
}
/**
- * Returns HTTP request headers.
- *
- * This method will try to extract request headers using two ways,
- * first, it will check if the method 'apache_request_headers()' is existed or not. If it does, then request headers will be taken from
- * there. If it does not exist, it will try to extract request headers
- * from the super global $_SERVER.
- *
- * @return array An array of request headers. Each header is represented
- * as an object of type HttpHeader.
+ * Returns HTTP request method.
*
+ * @return string
*/
- public static function getHeaders() : array {
- if (defined('__PHPUNIT_PHAR__') || self::get()->headersPool->getHeaders() == [] || http_response_code() === false) {
- //Always Refresh headers if in testing environment.
- self::extractHeaders();
- }
-
- return self::getHeadersPool()->getHeaders();
- }
- /**
- * Returns an associative array of request headers.
- *
- * @return array The indices of the array will be headers names and the
- * values are sub-arrays. Each array contains the values of the header.
- */
- public static function getHeadersAssoc() : array {
- $retVal = [];
- $headers = self::getHeaders();
-
- foreach ($headers as $headerObj) {
- if (!isset($retVal[$headerObj->getName()])) {
- $retVal[$headerObj->getName()] = [];
- }
- $retVal[$headerObj->getName()][] = $headerObj->getValue();
- }
-
- return $retVal;
+ public function getMethod() : string {
+ return $this->getRequestMethod();
}
/**
- * Returns the pool which is used to hold request headers.
+ * Returns the value of GET or POST parameter.
*
- * @return HeadersPool
- */
- public static function getHeadersPool() : HeadersPool {
- return self::get()->headersPool;
- }
- /**
- * Returns the name of request method which is used to call one of the services in the set.
- *
- * @return string Request method such as POST, GET, etc.... Default return
- * value is 'GET'. The default is usually returned in case the call to
- * this method was performed in CLI environment. To change request method
- * in CLI environment to something like 'POST' for testing, use the
- * function putenv('REQUEST_METHOD=POST').
+ * @param string $paramName
*
+ * @return string|null
*/
- public static function getMethod() : string {
- $meth = getenv('REQUEST_METHOD');
-
- if ($meth === false) {
- $meth = $_SERVER['REQUEST_METHOD'] ?? '';
- }
- $method = filter_var($meth, FILTER_SANITIZE_FULL_SPECIAL_CHARS);
-
-
- if (!in_array($method, self::METHODS)) {
- $method = 'GET';
- }
-
- return $method;
+ public function getParam(string $paramName) {
+ $params = $this->getParams();
+ return $params[trim($paramName)] ?? null;
}
- /**
- * Returns the value of a GET or POST parameter.
- *
- * This method will apply basic filtering to the value of the parameter before returning
- * it. The developer may need to apply extra filtering to make sure that the
- * value of the parameter is safe to use.
- *
- * @param string $paramName The name of the parameter. Note that if the value has extra
- * spaces, they will be trimmed.
- *
- * @return string|null The method will return the value of the parameter if
- * set as a string. Other than that, the method will return null.
- *
- */
- public static function getParam(string $paramName) {
- $trimmed = trim($paramName);
- $params = self::getParams();
- if (isset($params[$trimmed])) {
- return $params[$trimmed];
- }
-
- return null;
- }
/**
- * Returns the value of HTTP cookie given its name.
+ * Returns the value of a cookie.
*
- * @param string $cookieName The name of the cookie as it was sent from the client.
+ * @param string $cookieName
*
- * @return string|null If a cookie with given name exist on the request,
- * its value is returned. Other than that, null is returned.
+ * @return string|null
*/
- public static function getCookieValue(string $cookieName) {
+ public function getCookieValue(string $cookieName) {
$trimmedName = trim($cookieName);
- return self::filter(INPUT_COOKIE, $trimmedName);
+ if (isset($_COOKIE[$trimmedName])) {
+ return filter_var($_COOKIE[$trimmedName]);
+ }
+ return null;
}
+
/**
- * Returns an array that contains all POST or GET parameters.
+ * Returns all request parameters.
*
- * @return array An array that contains all POST or GET parameters. The
- * indices of the array are parameters names and the value of each index
- * is the value of the parameter.
+ * @return array
*/
- public static function getParams() : array {
- $requestMethod = self::getMethod();
+ public function getParams() : array {
+ $method = $this->getMethod();
$retVal = [];
-
- if ($requestMethod == RequestMethod::POST || $requestMethod == RequestMethod::PUT || $requestMethod == RequestMethod::PATCH) {
- foreach (array_keys($_POST) as $name) {
- $retVal[$name] = self::filter(INPUT_POST, $name);
+
+ if ($method == RequestMethod::GET) {
+ foreach ($_GET as $param => $val) {
+ $retVal[$param] = $this->filter(INPUT_GET, $param);
}
- } else if ($requestMethod == RequestMethod::DELETE || $requestMethod == RequestMethod::GET) {
- foreach (array_keys($_GET) as $name) {
- $retVal[$name] = self::filter(INPUT_GET, $name);
+ } else if ($method == RequestMethod::POST) {
+ foreach ($_POST as $param => $val) {
+ $retVal[$param] = $this->filter(INPUT_POST, $param);
}
}
-
+
return $retVal;
}
+
/**
- * Returns path part of a requested URI.
+ * Returns the path part of request URI.
*
- * @return string Path part of a requested URI.
+ * @return string
*/
- public static function getPath() : string {
- $path = self::getPathHelper('REQUEST_URI');
+ public function getPath() : string {
+ $path = $this->getPathHelper('REQUEST_URI');
- if (strlen($path) == 0) {
- $path = self::getPathHelper('X_ORIGINAL_URL');
-
- if (strlen($path) == 0) {
- $path = getenv('REQUEST_URI');
-
- if ($path === false || strlen($path) == 0) {
- $path = getenv('HTTP_REQUEST_URI');
-
- if ($path === false || strlen($path) == 0) {
- //Local dev server
- $path = $_SERVER['PATH_INFO'] ?? '';
- }
- }
- }
+ if ($path === null) {
+ $path = $this->getPathHelper('PATH_INFO');
}
- if (strlen($path) == 0) {
- return '/';
+ if ($path === null) {
+ $path = $this->getPathHelper('HTTP_REQUEST_URI');
}
- return parse_url($path, PHP_URL_PATH);
- }
- private static function getPathHelper(string $header) {
- $path = '';
- $headerVals = self::getHeader($header);
+ if ($path === null) {
+ $path = $this->getPathHelper('HTTP_X_ORIGINAL_URL');
+ }
- if (count($headerVals) != 0) {
- $path = trim($headerVals[0]);
+ if ($path === null) {
+ $path = $this->getPathHelper('SCRIPT_NAME');
}
- return $path;
+ if ($path === null) {
+ return '/';
+ }
+
+ return parse_url($path, PHP_URL_PATH);
}
+
/**
* Returns the URI of the requested resource.
*
- * @param string $pathToAppend If provided, this part will be
- * appended to the final URI. It is useful in case of having multiple
- * applications on same domain to have different paths.
- *
- * @return string The URI of the requested resource
- * (e.g. http://example.com/get-random?range=[1,100]).
+ * @param string $pathToAppend
*
+ * @return string
*/
- public static function getRequestedURI(string $pathToAppend = '') : string {
- $base = Uri::getBaseURL();
+ public function getRequestedURI(string $pathToAppend = '') : string {
+ $base = RequestUri::getBaseURL();
- $path = self::getPath();
-
- if (strpos($path, '?') !== false) {
- $split = explode('?', $path);
- $path = $split[0];
- }
-
- $cleanedPath = str_replace(trim(str_replace('\\', '/', $pathToAppend), '/'),'' ,trim(filter_var($path),'/'));
- $requestMethod = self::getMethod();
- $queryString = '';
-
-
- if ($requestMethod == RequestMethod::DELETE || $requestMethod == RequestMethod::GET) {
- $getParams = Request::getParams();
+ if (strlen($pathToAppend) != 0) {
+ $path = $this->getPath();
+ $cleanPath = trim($pathToAppend, '/');
- if (count($getParams) != 0) {
- $queryArr = [];
- foreach ($getParams as $name => $val) {
- $queryArr[] = $name.'='.$val;
+ if (strlen($cleanPath) != 0) {
+ if ($path[strlen($path) - 1] == '/') {
+ return $base.$path.$cleanPath;
+ } else {
+ return $base.$path.'/'.$cleanPath;
}
- $queryString = '?'.implode('&', $queryArr);
}
}
- return $base.'/'.trim($cleanedPath, '/').$queryString;
+
+ $uri = $base.$this->getPath();
+
+ if (!empty($_GET)) {
+ $uri .= '?'.http_build_query($_GET);
+ }
+
+ return $uri;
}
+
/**
- * Returns an object that holds all information about requested URI.
- *
- * @return Uri an object that holds all information about requested URI.
+ * Returns an object of type 'Uri'.
*
+ * @return RequestUri
*/
- public static function getUri() : Uri {
- return new Uri(self::getRequestedURI());
+ public function getUri() : RequestUri {
+ return new RequestUri($this->getRequestedURI());
+ }
+
+ private function getMethodFromGlobals() : string {
+ $meth = getenv('REQUEST_METHOD');
+
+ if ($meth === false) {
+ $meth = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : RequestMethod::GET;
+ }
+
+ $method = filter_var($meth);
+
+ if ($method !== false && in_array($method, RequestMethod::getAll())) {
+ return $method;
+ }
+
+ return RequestMethod::GET;
}
- private static function extractHeaders() {
- self::get()->headersPool = new HeadersPool();
+ private function extractHeaders() {
+ $this->getHeadersPool()->clear();
+
if (function_exists('apache_request_headers')) {
$headers = apache_request_headers();
-
+
foreach ($headers as $k => $v) {
- self::get()->headersPool->addHeader($k, filter_var($v, FILTER_SANITIZE_FULL_SPECIAL_CHARS));
+ $this->addHeader($k, filter_var($v, FILTER_SANITIZE_FULL_SPECIAL_CHARS));
}
- }
-
- if (isset($_SERVER)) {
- $headersArr = self::getRequestHeadersFromServer();
-
+ } else {
+ $headersArr = $this->getRequestHeadersFromServer();
+
foreach ($headersArr as $header) {
- self::get()->headersPool->addHeader($header->getName(), $header->getValue(), null);
+ $this->addHeader($header->getName(), $header->getValue());
}
}
}
- private static function filter($inputSource, $varName) {
- $val = filter_input($inputSource, $varName);
+ private function filter($inputSource, $varName) {
+ $val = filter_input($inputSource, $varName);
+
if ($val === null) {
if ($inputSource == INPUT_POST && isset($_POST[$varName])) {
$val = filter_var(urldecode($_POST[$varName]));
@@ -402,36 +277,39 @@ private static function filter($inputSource, $varName) {
$val = filter_var(urldecode($_COOKIE[$varName]));
}
}
-
+
return $val;
}
- /**
- * Collect request headers from the array $_SERVER.
- * @return array
- */
- private static function getRequestHeadersFromServer() : array {
- $retVal = [];
- foreach ($_SERVER as $k => $v) {
- $split = explode('_', $k);
-
- if ($split[0] == 'HTTP') {
- $headerName = '';
- $count = count($split);
+ private function getPathHelper(string $header) {
+ $envVal = getenv($header);
+ if ($envVal !== false) {
+ return $envVal;
+ }
+
+ if (isset($_SERVER[$header])) {
+ return $_SERVER[$header];
+ }
+
+ $headerVals = $this->getHeader($header);
+
+ if (count($headerVals) == 1) {
+ return $headerVals[0];
+ }
+
+ return null;
+ }
- for ($x = 0 ; $x < $count ; $x++) {
- if ($x + 1 == $count && $split[$x] != 'HTTP') {
- $headerName = $headerName.$split[$x];
- } else if ($x == 1 && $split[$x] != 'HTTP') {
- $headerName = $split[$x].'-';
- } else if ($split[$x] != 'HTTP') {
- $headerName = $headerName.$split[$x].'-';
- }
- }
- $retVal[] = new HttpHeader($headerName, filter_var($v, FILTER_SANITIZE_FULL_SPECIAL_CHARS));
+ private function getRequestHeadersFromServer() : array {
+ $retVal = [];
+
+ foreach ($_SERVER as $name => $value) {
+ if (substr($name, 0, 5) == 'HTTP_') {
+ $name = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))));
+ $retVal[] = new HttpHeader($name, $value);
}
}
-
+
return $retVal;
}
}
diff --git a/WebFiori/Http/RequestParameter.php b/WebFiori/Http/RequestParameter.php
index 0160c5bc..50837dfa 100644
--- a/WebFiori/Http/RequestParameter.php
+++ b/WebFiori/Http/RequestParameter.php
@@ -2,7 +2,7 @@
/**
* This file is licensed under MIT License.
*
- * Copyright (c) 2019 Ibrahim BinAlshikh
+ * Copyright (c) 2019 WebFiori Framework
*
* For more information on the license, please visit:
* https://github.com/WebFiori/http/blob/master/LICENSE
diff --git a/WebFiori/Http/RequestUri.php b/WebFiori/Http/RequestUri.php
new file mode 100644
index 00000000..cacb70de
--- /dev/null
+++ b/WebFiori/Http/RequestUri.php
@@ -0,0 +1,382 @@
+getName();
+ }, $this->getParameters());
+ }
+ /**
+ * Returns the base URL of the framework.
+ *
+ * The returned value will depend on the folder where the library files
+ * are located. For example, if your domain is 'example.com' and the library
+ * is placed at the root and the requested resource is 'http://example.com/x/y/z',
+ * then the base URL will be 'http://example.com/'. If the library is
+ * placed inside a folder in the server which has the name 'system', and
+ * the same resource is requested, then the base URL will be
+ * 'http://example.com/system'.
+ *
+ * @return string The base URL (such as 'http//www.example.com/')
+ *
+ */
+ public static function getBaseURL(?array $serverInputs = null) : string {
+ $server = $serverInputs ?? $_SERVER;
+ $tempHost = $server['HTTP_HOST'] ?? '127.0.0.1';
+ $host = trim(filter_var($tempHost),'/');
+
+ if (isset($server['HTTPS'])) {
+ $secureHost = filter_var($server['HTTPS']);
+ } else {
+ $secureHost = '';
+ }
+ $protocol = 'http://';
+ $useHttp = defined('USE_HTTP') && USE_HTTP === true;
+
+ if (strlen($secureHost) != 0 && !$useHttp) {
+ $protocol = "https://";
+ }
+
+ if (isset($server['DOCUMENT_ROOT'])) {
+ $docRoot = filter_var($server['DOCUMENT_ROOT']);
+ } else {
+ //Fix for IIS since the $_SERVER['DOCUMENT_ROOT'] is not set
+ //in some cases
+ $docRoot = getcwd();
+ }
+
+ $docRootLen = strlen($docRoot);
+
+ if ($docRootLen == 0) {
+ $docRoot = __DIR__;
+ $docRootLen = strlen($docRoot);
+ }
+
+ if (!defined('ROOT_PATH')) {
+ define('ROOT_PATH', __DIR__);
+ }
+ $toAppend = str_replace('\\', '/', substr(ROOT_PATH, $docRootLen, strlen(ROOT_PATH) - $docRootLen));
+
+ if (defined('WF_PATH_TO_REMOVE')) {
+ $toAppend = str_replace(str_replace('\\', '/', WF_PATH_TO_REMOVE),'' ,$toAppend);
+ }
+ $xToAppend = str_replace('\\', '/', $toAppend);
+
+ if (defined('WF_PATH_TO_APPEND')) {
+ $xToAppend = $xToAppend.'/'.trim(str_replace('\\', '/', WF_PATH_TO_APPEND), '/');
+ }
+
+ if (strlen($xToAppend) == 0) {
+ return $protocol.$host;
+ } else {
+ return $protocol.$host.'/'.trim($xToAppend, '/');
+ }
+ }
+ /**
+ * Returns the value of URI parameter given its name.
+ *
+ * A URI parameter is a string which is defined while creating the route.
+ * it is name is included between '{}'.
+ *
+ * @param string $varName The name of the parameter. Note that this value
+ * must not include braces.
+ *
+ * @return string|null The method will return the value of the
+ * parameter if found. If the parameter is not set or the parameter
+ * does not exist, the method will return null.
+ *
+ */
+ public function getParameterValue(string $varName) : ?string {
+ $param = $this->getParameter($varName);
+
+ if ($param !== null) {
+ return $param->getValue();
+ }
+
+ return null;
+ }
+ /**
+ * Creates new instance of the class.
+ *
+ * @param string $requestedUri The URI such as 'https://www3.programmingacademia.com:80/{some-var}/hell/{other-var}/?do=dnt&y=2018#xyz'
+ *
+ * @throws InvalidArgumentException
+ */
+ public function __construct(string $requestedUri = '') {
+ parent::__construct($requestedUri);
+ $this->allowedMethods = [];
+ $this->vars = [];
+ $addedParams = [];
+ $pathArr = $this->getPathArray();
+
+
+ foreach($pathArr as $part) {
+ $conv = mb_convert_encoding(urldecode($part), 'UTF-8', 'ISO-8859-1');
+
+ if ($conv[0] == '{' && $conv[strlen($conv) - 1] == '}') {
+ $name = trim($part, '{}');
+
+ if (!in_array($name, $addedParams)) {
+ $addedParams[] = $name;
+ $this->vars[] = new UriParameter($name);
+ }
+ }
+
+ }
+ $this->verifyOrderOfParams();
+ }
+ private function verifyOrderOfParams() {
+ $currentOptional = false;
+
+ foreach($this->getParameters() as $param) {
+ if ($currentOptional == true && !$param->isOptional()) {
+ throw new \Exception('Requred paramater cannot appear after optional');
+ }
+ $currentOptional = $param->isOptional() || $currentOptional;
+ }
+ }
+
+ /**
+ * Adds new request method to the allowed methods.
+ *
+ * @param string $method The request method (e.g. 'GET', 'POST', 'PUT', etc...).
+ */
+ public function addRequestMethod(string $method) : RequestUri {
+ $normalizedMethod = strtoupper(trim($method));
+
+ if (!in_array($normalizedMethod, $this->allowedMethods)) {
+ $this->allowedMethods[] = $normalizedMethod;
+ }
+ return $this;
+ }
+
+ /**
+ * Adds a value to allowed URI parameter values.
+ *
+ * @param string $paramName The name of the parameter.
+ * @param string $value The value to add.
+ */
+ public function addAllowedParameterValue(string $paramName, string $value) : RequestUri {
+
+ $normalized = trim($paramName);
+ foreach ($this->getParameters() as $param) {
+ if ($param->getName() == $normalized) {
+ $param->addAllowedValue($value);
+ break;
+ }
+ }
+ return $this;
+ }
+ public function addAllowedParameterValues(string $name, array $vals) : RequestUri {
+ $normalizedName = trim($name);
+
+ foreach ($this->getParameters() as $param) {
+ if ($param->getName() == $normalizedName) {
+ $param->addAllowedValues($vals);
+ break;
+ }
+ }
+ return $this;
+ }
+
+ /**
+ * Checks if two URIs are equal or not.
+ *
+ * @param RequestUri $otherUri An object of type 'RequestUri'.
+ *
+ * @return bool The method will return true if the URIs are
+ * equal. False if not.
+ */
+ public function equals(Uri $otherUri) : bool {
+ if (!parent::equals($otherUri)) {
+ return false;
+ }
+ $thisPath = $this->getPath();
+ $otherPath = $otherUri->getPath();
+
+ $thisMethods = $this->getRequestMethods();
+ $otherMethods = $otherUri->getRequestMethods();
+
+ if (count($thisMethods) != count($otherMethods)) {
+ return false;
+ }
+
+ foreach ($thisMethods as $method) {
+ if (!in_array($method, $otherMethods)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns the value of URI parameter given its name.
+ *
+ * @param string $paramName The name of the parameter.
+ *
+ * @return UriParameter|null If a parameter which has the given name
+ * is found, it will be returned. If no such parameter, the method will
+ * return null.
+ */
+ public function getParameter(string $paramName) : ?UriParameter {
+
+ foreach ($this->getParameters() as $param) {
+ if ($param->getName() == $paramName) {
+ return $param;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns an array that contains all URI parameters.
+ *
+ * @return array An array that contains objects of type 'UriParameter'.
+ */
+ public function getParameters() : array {
+ return $this->vars;
+ }
+
+ /**
+ * Returns an array that contains allowed URI parameters values.
+ *
+ * @return array
+ */
+ public function getAllowedParameterValues(string $varName) : array {
+
+ $param = $this->getParameter($varName);
+ if ($param !== null) {
+
+ return $param->getAllowedValues();
+ }
+
+ return [];
+ }
+
+ /**
+ * Returns an array that contains all allowed request methods.
+ *
+ * @return array An array that contains all allowed request methods.
+ */
+ public function getRequestMethods() : array {
+ return $this->allowedMethods;
+ }
+
+ /**
+ * Checks if the URI has any parameters or not.
+ *
+ * @return bool The method will return true if the URI has any parameters.
+ * false if not.
+ */
+ public function hasParameters() : bool {
+ return count($this->getParameters()) > 0;
+ }
+
+ /**
+ * Checks if the URI has a specific parameter or not.
+ *
+ * @param string $paramName The name of the parameter.
+ *
+ * @return bool The method will return true if the parameter
+ * is found. false if not.
+ */
+ public function hasParameter(string $paramName) : bool {
+ return $this->getParameter($paramName) !== null;
+ }
+
+ /**
+ * Checks if all URI parameters have values or not.
+ *
+ * @return bool The method will return true if all URI parameters
+ * have values. false if not.
+ */
+ public function isAllParametersSet() : bool {
+ $uriVars = $this->getParameters();
+
+ foreach ($uriVars as $param) {
+ if ($param->getValue() === null && !$param->isOptional()) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Checks if a request method is allowed or not.
+ *
+ * @param string $method The request method (e.g. 'GET', 'POST', 'PUT', etc...).
+ * If not provided, the method will attempt to get request method using the environment
+ * variable 'REQUEST_METHOD'.
+ *
+ * @return bool The method will return true if the method is allowed.
+ * If no request methods are specified, the method will return true.
+ * Other than that, the method will return false.
+ */
+ public function isRequestMethodAllowed(?string $method = null) : bool {
+ if ($method === null) {
+ $method = getenv('REQUEST_METHOD');
+ if (!in_array($method, RequestMethod::getAll())) {
+ return false;
+ }
+ }
+ $normalizedMethod = strtoupper(trim($method));
+ $methods = $this->getRequestMethods();
+
+ return count($methods) == 0 || in_array($normalizedMethod, $methods);
+ }
+
+ /**
+ * Sets the value of a URI parameter.
+ *
+ * @param string $paramName The name of the parameter.
+ * @param string $value The value to set.
+ */
+ public function setParameterValue(string $paramName, string $value) : bool {
+ $param = $this->getParameter($paramName);
+
+ if ($param !== null) {
+ return $param->setValue($value);
+ }
+ return false;
+ }
+
+ /**
+ * Sets the array of allowed request methods.
+ *
+ * @param array $methods An array that contains request methods names.
+ */
+ public function setRequestMethods(array $methods) : RequestUri {
+ $this->allowedMethods = [];
+
+ foreach ($methods as $method) {
+ $this->addRequestMethod($method);
+ }
+ return $this;
+ }
+}
diff --git a/WebFiori/Http/Response.php b/WebFiori/Http/Response.php
index 204f393a..22160469 100644
--- a/WebFiori/Http/Response.php
+++ b/WebFiori/Http/Response.php
@@ -2,7 +2,7 @@
/**
* This file is licensed under MIT License.
*
- * Copyright (c) 2019 Ibrahim BinAlshikh
+ * Copyright (c) 2019 WebFiori Framework
*
* For more information on the license, please visit:
* https://github.com/WebFiori/http/blob/master/LICENSE
diff --git a/WebFiori/Http/Uri.php b/WebFiori/Http/Uri.php
index 61390740..80f35e34 100644
--- a/WebFiori/Http/Uri.php
+++ b/WebFiori/Http/Uri.php
@@ -2,7 +2,7 @@
/**
* This file is licensed under MIT License.
*
- * Copyright (c) 2019 Ibrahim BinAlshikh
+ * Copyright (c) 2019 WebFiori Framework
*
* For more information on the license, please visit:
* https://github.com/WebFiori/http/blob/master/LICENSE
@@ -10,171 +10,98 @@
namespace WebFiori\Http;
use InvalidArgumentException;
+
/**
- * A class that is used to split URIs and get their parameters.
- *
- * The main aim of this class is to extract URI parameters including:
- *
- * - Host
- * - Authority
- * - Fragment (if any)
- * - Path
- * - Port (if any)
- * - Query string (if any)
- * - Scheme
- *
- * For more information on URI structure, visit Wikipedia.
- *
+ * A class for representing and parsing URIs.
+ *
* @author Ibrahim
- *
*/
class Uri {
/**
- *
- * @var array
+ * An array that contains URI parts.
*
- */
- private $allowedRequestMethods;
- /**
- * The URI broken into its subcomponents (scheme, authority ...) as an associative
- * array.
- * @var array
+ * @var array
*/
private $uriBroken;
+
/**
- * Creates new instance.
+ * Creates new instance of the class.
*
- * @param string $requestedUri The URI such as 'https://www3.webfiori.com:80/{some-var}/hell/{other-var}/?do=dnt&y=#xyz'
- */
- public function __construct(string $requestedUri) {
- $this->allowedRequestMethods = [];
- $this->uriBroken = self::splitURI($requestedUri);
-
- if (gettype($this->uriBroken) != 'array') {
- throw new InvalidArgumentException('Invalid URI given.');
- }
-
- if (!$this->checkOptionalParamsOrder()) {
- throw new InvalidArgumentException('Incorrect parameters order.');
- }
- $this->uriBroken['vars-possible-values'] = [];
-
- foreach ($this->getParametersNames() as $varName) {
- $this->uriBroken['vars-possible-values'][$varName] = [];
- }
- }
-
- /**
- * Adds a request method to the allowed set of methods at which the URI can
- * be called with.
- *
- * @param string $method A string such as 'GET' or 'POST'. Note that the
- * value must exist in the array Request::METHODS, or it will be not added.
+ * @param string $requestedUri The URI such as 'https://www3.programmingacademia.com:80/{some-var}/hell/{other-var}/?do=dnt&y=2018#xyz'
*
+ * @throws InvalidArgumentException
*/
- public function addRequestMethod(string $method) {
- if (in_array($method, Request::METHODS)) {
- $this->allowedRequestMethods[] = $method;
- }
- }
- /**
- * Adds a possible value for a URI parameter.
- *
- * This is used in constructing the sitemap node of the URI. If a value is
- * provided, then it will be part of the URI that will appear in the sitemap.
- *
- * @param string $varName The name of the parameter. It must be existed as the path part in the URI.
- *
- * @param string $varValue The value of the parameter. Note that any extra spaces
- * in the value will be trimmed.
- *
- */
- public function addVarValue(string $varName, string $varValue) {
- $trimmed = trim($varName);
- $trimmedVal = trim($varValue);
-
- if (strlen($trimmedVal) != 0
- && isset($this->uriBroken['vars-possible-values'][$trimmed])
- && !in_array($trimmedVal, $this->uriBroken['vars-possible-values'][$trimmed])) {
- $this->uriBroken['vars-possible-values'][$trimmed][] = $trimmedVal;
- }
- }
- /**
- * Adds multiple values to URI parameter.
- *
- * @param string $varName The name of the parameter.
- *
- * @param array $arrayOfValues An array that contains all possible values for
- * the parameter.
- *
- */
- public function addVarValues(string $varName, array $arrayOfValues) {
- if (gettype($arrayOfValues) == 'array') {
- foreach ($arrayOfValues as $val) {
- $this->addVarValue($varName, $val);
+ public function __construct(string $requestedUri = '') {
+ if (strlen(trim($requestedUri)) == 0) {
+ throw new InvalidArgumentException('URI must be non-empty string');
+ } else {
+ $this->uriBroken = self::splitURI($requestedUri);
+
+ if ($this->uriBroken === false) {
+ throw new InvalidArgumentException('Invalid URI: \''.$requestedUri.'\'');
}
}
}
/**
- * Checks if two URIs are equal or not.
+ * Returns the original requested URI.
*
- * Two URIs are considered equal if they have the same authority and the
- * same path name.
+ * @param boolean $incQueryStr If set to true, the query string part
+ * will be included in the URL. Default is false.
*
- * @param Uri $otherUri The URI which 'this' URI will be checked against.
+ * @param boolean $incFragment If set to true, the fragment part
+ * will be included in the URL. Default is false.
*
- * @return boolean The method will return true if the URIs are
- * equal.
+ * @return string The original requested URI.
*
*/
- public function equals(Uri $otherUri) : bool {
- $isEqual = true;
+ public function getUri(bool $incQueryStr = false, bool $incFragment = false) : string {
+ $retVal = $this->getScheme().':'.$this->getAuthority().$this->getPath();
- if ($this->getAuthority() == $otherUri->getAuthority()) {
- $thisPathNames = $this->getPathArray();
- $otherPathNames = $otherUri->getPathArray();
- $booleansArr = [];
+ if ($incQueryStr === true && $incFragment === true) {
+ $queryStr = $this->getQueryString();
- foreach ($thisPathNames as $path1) {
- $booleansArr[] = in_array($path1, $otherPathNames);
+ if (strlen($queryStr) != 0) {
+ $retVal .= '?'.$queryStr;
}
+ $fragment = $this->getFragment();
- foreach ($otherPathNames as $path) {
- $booleansArr[] = in_array($path, $thisPathNames);
+ if (strlen($fragment) != 0) {
+ $retVal .= '#'.$fragment;
}
+ } else {
+ if ($incQueryStr === true && $incFragment === false) {
+ $queryStr = $this->getQueryString();
- foreach ($booleansArr as $bool) {
- $isEqual = $isEqual && $bool;
- }
+ if (strlen($queryStr) != 0) {
+ $retVal .= '?'.$queryStr;
+ }
+ } else {
+ if ($incQueryStr === false && $incFragment === true) {
+ $fragment = $this->getFragment();
- return $isEqual;
+ if (strlen($fragment) != 0) {
+ $retVal .= '#'.$fragment;
+ }
+ }
+ }
}
- return false;
+ return $retVal;
}
/**
- * Returns authority part of the URI.
+ * Returns the authority part of the URI.
*
* @return string The authority part of the URI. Usually,
- * it is a string in the form '//www.example.com:80'.
- *
+ * it is the sub-domain + domain name + port number.
*/
public function getAuthority() : string {
return $this->uriBroken['authority'];
}
+
/**
* Returns the base URL of the framework.
*
- * The returned value will depend on the folder where the library files
- * are located. For example, if your domain is 'example.com' and the library
- * is placed at the root and the requested resource is 'http://example.com/x/y/z',
- * then the base URL will be 'http://example.com/'. If the library is
- * placed inside a folder in the server which has the name 'system', and
- * the same resource is requested, then the base URL will be
- * 'http://example.com/system'.
- *
- * @return string The base URL (such as 'http//www.example.com/')
- *
+ * @return string The base URL (such as 'https://example.com/' or 'http://127.0.0.1/')
*/
public static function getBaseURL() : string {
$tempHost = $_SERVER['HTTP_HOST'] ?? '127.0.0.1';
@@ -227,8 +154,9 @@ public static function getBaseURL() : string {
return $protocol.$host.'/'.trim($xToAppend, '/');
}
}
+
/**
- * Returns an associative array which contains all URI parts.
+ * Returns an array that contains all URI parts.
*
* @return array The method will return an associative array that
* contains the components of the URI. The array will have the
@@ -236,360 +164,153 @@ public static function getBaseURL() : string {
*
* - uri: The original URI.
* - port: The port number taken from the authority part.
- * - host: Will be always empty string.
+ * - host: FQDN taken from the authority part.
* - authority: Authority part of the URI.
* - scheme: Scheme part of the URI (e.g. http or https).
* - query-string: Query string if the URI has any.
* - fragment: Any string that comes after the character '#' in the URI.
* - path: An array that contains the names of path directories
* - query-string-vars: An array that contains query string parameter and values.
- * - uri-vars: An array that contains URI path parameter and values.
+ * - uri-vars: An array that contains URI parameters (e.g. {id}, {name}, etc...).
*
- *
*/
public function getComponents() : array {
return $this->uriBroken;
}
+
/**
- * Returns fragment part of the URI.
+ * Returns the fragment part of the URI.
*
- * @return string Fragment part of the URI. The fragment in the URI is
+ * @return string The fragment part of the URI. The fragment in the URI is
* any string that comes after the character '#'.
- *
*/
public function getFragment() : string {
return $this->uriBroken['fragment'];
}
+
/**
- * Returns host name from the host part of the URI.
- *
- * @return string The host name such as 'www.webfiori.com'.
+ * Returns the host name from the authority part of the URI.
*
+ * @return string The host name such as 'www.example.com'.
*/
public function getHost() : string {
return $this->uriBroken['host'];
}
/**
- * Returns URI parameter given its name.
- *
- * @param string $name The name of the parameter.
- *
- * @return UriParameter|null If such parameter is found, it will be returned
- * as an object. Other than that, null is returned.
- */
- public function getParameter(string $name) {
- foreach ($this->getParameters() as $obj) {
- if ($obj->getName() == $name) {
- return $obj;
- }
- }
-
- return null;
- }
- /**
- * Returns an array which contains URI parameters as objects.
- *
- * @return array An indexed array which contains URI parameters as
- * objects of type UriParameter.
- *
- */
- public function getParameters() : array {
- return $this->uriBroken['uri-vars'];
- }
- public function getParametersNames() : array {
- $retVal = [];
-
- foreach ($this->getParameters() as $paramObj) {
- $retVal[] = $paramObj->getName();
- }
-
- return $retVal;
- }
- /**
- * Returns the value of URI parameter given its name.
- *
- * A URI parameter is a string which is defined while creating the route.
- * it is name is included between '{}'.
- *
- * @param string $varName The name of the parameter. Note that this value
- * must not include braces.
- *
- * @return string|null The method will return the value of the
- * parameter if found. If the parameter is not set or the parameter
- * does not exist, the method will return null.
- *
- */
- public function getParameterValue(string $varName) {
- $param = $this->getParameter($varName);
-
- if ($param !== null) {
- return $param->getValue();
- }
-
- return null;
- }
- /**
- * Returns an array that contains possible values for a URI parameter.
- *
- * @param string $varName The name of the parameter.
+ * Returns an array which contains the names of URI directories.
*
- * @return array The method will return an array that contains all possible
- * values for the parameter which was added using the method Router::addUriVarValue().
- * If the parameter does not exist, the array will be empty.
+ * @return array An array which contains the names of URI directories.
+ * For example, if the path part of the URI is '/path1/path2', the
+ * array will contain the value 'path1' at index 0 and 'path2' at index 1.
*
*/
- public function getParameterValues(string $varName) : array {
- $trimmed = trim($varName);
-
- if (isset($this->uriBroken['vars-possible-values'][$trimmed])) {
- return $this->uriBroken['vars-possible-values'][$trimmed];
- }
-
- return [];
+ public function getPathArray() : array {
+ return $this->uriBroken['path'];
}
/**
* Returns the path part of the URI.
*
* @return string A string such as '/path1/path2/path3'.
- *
*/
public function getPath() : string {
- $retVal = '';
-
- foreach ($this->uriBroken['path'] as $dir) {
- $retVal .= '/'.$dir;
+ $path = $this->uriBroken['path'];
+
+ if (count($path) == 0) {
+ return '/';
}
-
- return $retVal;
- }
- /**
- * Returns an array which contains the names of URI directories.
- *
- * @return array An array which contains the names of URI directories.
- * For example, if the path part of the URI is '/path1/path2', the
- * array will contain the value 'path1' at index 0 and 'path2' at index 1.
- *
- */
- public function getPathArray() : array {
- return $this->uriBroken['path'];
+
+ return '/'.implode('/', $path);
}
+
/**
- * Returns port number of the authority part of the URI.
- *
- * @return string Port number of the authority part of the URI. If
- * port number was not specified, the method will return empty string.
+ * Returns the port number of the authority part of the URI.
*
+ * @return string The port number such as '80' or '443'. If no port
+ * number is specified, the method will return empty string.
*/
public function getPort() : string {
return $this->uriBroken['port'];
}
+
/**
* Returns the query string that was appended to the URI.
*
- * @return string The query string that was appended to the URI.
- * If the URI has no query string, the method will return empty
- * string.
- *
+ * @return string The query string such as 'do=dnt&y=2018'. If the URI
+ * has no query string, the method will return empty string.
*/
public function getQueryString() : string {
return $this->uriBroken['query-string'];
}
+
/**
* Returns an associative array which contains query string parameters.
*
- * @return array An associative array which contains query string parameters.
- * the keys will be acting as the names of the parameters and the values
- * of each parameter will be in its key.
- *
+ * @return array An associative array. The keys will be parameters
+ * names and the values are parameters values. If the URI has no query
+ * string, the method will return empty array.
*/
public function getQueryStringVars() : array {
return $this->uriBroken['query-string-vars'];
}
- /**
- * Returns an array that holds all allowed request methods at which the
- * URI can be called with.
- *
- * @return array An array that holds strings such as 'GET' or 'POST'.
- *
- */
- public function getRequestMethods() : array {
- return $this->allowedRequestMethods;
- }
+
/**
* Returns the scheme part of the URI.
*
- * @return string The scheme part of the URI. Usually, it is called protocol
- * (like http, ftp).
- *
+ * @return string The scheme part of the URI. Usually, it can be
+ * 'http' or 'https'.
*/
public function getScheme() : string {
return $this->uriBroken['scheme'];
}
+
/**
- * Returns the original requested URI.
+ * Splits a string based on character mask.
*
- * @param boolean $incQueryStr If set to true, the query string part
- * will be included in the URL. Default is false.
+ * @param string $split The string to split.
*
- * @param boolean $incFragment If set to true, the fragment part
- * will be included in the URL. Default is false.
+ * @param string $char The character that the split is based on.
*
- * @return string The original requested URI.
+ * @param string $encoded The character when encoded in URI.
*
+ * @return array
*/
- public function getUri(bool $incQueryStr = false, bool $incFragment = false) : string {
- $retVal = $this->getScheme().':'.$this->getAuthority().$this->getPath();
-
- if ($incQueryStr === true && $incFragment === true) {
- $queryStr = $this->getQueryString();
+ private static function _queryOrFragment(string $split, string $char, string $encoded) : array {
+ $split2 = explode($char, $split);
+ $spCount = count($split2);
- if (strlen($queryStr) != 0) {
- $retVal .= '?'.$queryStr;
- }
- $fragment = $this->getFragment();
+ if ($spCount > 2) {
+ $temp = [];
- if (strlen($fragment) != 0) {
- $retVal .= '#'.$fragment;
+ for ($x = 0 ; $x < $spCount - 1 ; $x++) {
+ $temp[] = $split2[$x];
}
- } else {
- if ($incQueryStr === true && $incFragment === false) {
- $queryStr = $this->getQueryString();
+ $lastStr = $split2[$spCount - 1];
- if (strlen($queryStr) != 0) {
- $retVal .= '?'.$queryStr;
- }
+ if (strlen($lastStr) == 0) {
+ $split2 = [
+ implode($encoded, $temp).$encoded
+ ];
} else {
- if ($incQueryStr === false && $incFragment === true) {
- $fragment = $this->getFragment();
-
- if (strlen($fragment) != 0) {
- $retVal .= '#'.$fragment;
- }
- }
+ $split2 = [
+ implode($encoded, $temp),
+ $split2[$spCount - 1]
+ ];
}
}
- return $retVal;
- }
- /**
- * Checks if the URI has a parameter or not given its name.
- *
- * A parameter is a string which is defined while creating the route.
- * it is name is included between '{}'.
- *
- * @param string $varName The name of the parameter.
- *
- * @return boolean If the given parameter name is exist, the method will
- * return true. Other than that, the method will return false.
- *
- */
- public function hasParameter(string $varName) : bool {
- return in_array($varName, $this->getParametersNames());
- }
- /**
- * Checks if the URI has any parameters or not.
- *
- * A parameter is a string which is defined while creating the route.
- * it is name is included between '{}'.
- *
- * @return bool If the URI has any parameters, the method will
- * return true.
- *
- */
- public function hasParameters() : bool {
- return count($this->getParameters()) != 0;
- }
- /**
- * Checks if all URI parameters has values or not.
- *
- * @return bool The method will return true if all non-optional URI
- * parameters have a value other than null.
- *
- */
- public function isAllParametersSet() : bool {
- $canRoute = true;
-
- foreach ($this->getParameters() as $val) {
- $canRoute = $canRoute && ($val->isOptional() || $val->getValue() != null);
- }
-
- return $canRoute;
- }
-
- /**
- * Checks if URI is fetched using allowed request method or not.
- *
- * @return boolean The method will return true in two cases, if the array
- * that holds allowed request methods is empty or request method is existed
- * in the allowed request methods. Other than that, the method will return
- * false.
- *
- */
- public function isRequestMethodAllowed() : bool {
- $methods = $this->getRequestMethods();
-
- return count($methods) == 0 || in_array(Request::getMethod(), $this->getRequestMethods());
- }
-
- /**
- * Sets the value of a URI parameter.
- *
- * A parameter is a string which is defined while creating the route.
- * it is name is included between '{}'.
- *
- * @param string $varName The name of the parameter.
- *
- * @param string $value The value of the parameter.
- *
- * @return bool The method will return true if the parameter
- * was set. If the parameter does not exist, the method will return false.
- *
- */
- public function setParameterValue(string $varName, string $value) : bool {
- $param = $this->getParameter($varName);
-
- if ($param !== null) {
- $param->setValue($value);
-
- return true;
- }
-
- return false;
+ return $split2;
}
- /**
- * Adds a set of request methods to the allowed methods at which the URI
- * can be called with.
- *
- * @param array $methods An array that holds strings such as 'GET' or 'POST'.
- *
- */
- public function setRequestMethods(array $methods) {
- foreach ($methods as $m) {
- $this->addRequestMethod($m);
- }
+ public function equals(Uri $uri) : bool {
+ return $this->getUri(true, true) == $uri->getUri(true, true);
}
/**
- * Breaks a URI into its basic components.
+ * Splits a URI into its basic components.
*
- * @param string $uri The URI that will be broken.
- *
- * @return array|boolean If the given URI is not valid,
- * the Method will return false. Other than that, The method will return an associative array that
- * contains the components of the URI. The array will have the
- * following indices:
- *
- * - uri: The original URI.
- * - port: The port number taken from the authority part.
- * - host: Will be always empty string.
- * - authority: Authority part of the URI.
- * - scheme: Scheme part of the URI (e.g. http or https).
- * - query-string: Query string if the URI has any.
- * - fragment: Any string that comes after the character '#' in the URI.
- * - path: An array that contains the names of path directories
- * - query-string-vars: An array that contains query string parameter and values.
- * - uri-vars: An array that contains URI path parameters and values.
- *
+ * @param string $uri The URI that will be split.
*
+ * @return array|bool If the given URI is not valid,
+ * the method will return false. Other than that, The method will return an associative array that
+ * contains the components of the URI.
*/
public static function splitURI(string $uri) {
$validate = filter_var(str_replace(' ', '%20', $uri),FILTER_VALIDATE_URL);
@@ -649,15 +370,6 @@ public static function splitURI(string $uri) {
if ($dirName != '') {
$retVal['path'][] = mb_convert_encoding(urldecode($dirName), 'UTF-8', 'ISO-8859-1');
-
- if ($dirName[0] == '{' && $dirName[strlen($dirName) - 1] == '}') {
- $name = trim($split4[$x], '{}');
-
- if (!in_array($name, $addedParams)) {
- $addedParams[] = $name;
- $retVal['uri-vars'][] = new UriParameter($name);
- }
- }
}
}
//now extract port number from the authority (if any)
@@ -675,55 +387,4 @@ public static function splitURI(string $uri) {
return $retVal;
}
-
- /**
- * Splits a string based on character mask.
- *
- * @param string $split The string to split.
- *
- * @param string $char The character that the split is based on.
- *
- * @param string $encoded The character when encoded in URI.
- *
- * @return array
- */
- private static function _queryOrFragment(string $split, string $char, string $encoded) : array {
- $split2 = explode($char, $split);
- $spCount = count($split2);
-
- if ($spCount > 2) {
- $temp = [];
-
- for ($x = 0 ; $x < $spCount - 1 ; $x++) {
- $temp[] = $split2[$x];
- }
- $lastStr = $split2[$spCount - 1];
-
- if (strlen($lastStr) == 0) {
- $split2 = [
- implode($encoded, $temp).$encoded
- ];
- } else {
- $split2 = [
- implode($encoded, $temp),
- $split2[$spCount - 1]
- ];
- }
- }
-
- return $split2;
- }
- private function checkOptionalParamsOrder() : bool {
- $hasOptional = false;
-
- foreach ($this->getParameters() as $obj) {
- $hasOptional = $hasOptional || $obj->isOptional();
-
- if ($hasOptional && !$obj->isOptional()) {
- return false;
- }
- }
-
- return true;
- }
}
diff --git a/WebFiori/Http/UriParameter.php b/WebFiori/Http/UriParameter.php
index 8e27fb2f..b551ef4d 100644
--- a/WebFiori/Http/UriParameter.php
+++ b/WebFiori/Http/UriParameter.php
@@ -2,7 +2,7 @@
/**
* This file is licensed under MIT License.
*
- * Copyright (c) 2019 Ibrahim BinAlshikh
+ * Copyright (c) 2019 WebFiori Framework
*
* For more information on the license, please visit:
* https://github.com/WebFiori/http/blob/master/LICENSE
@@ -30,6 +30,7 @@ class UriParameter {
* @var string
*/
private $value;
+ private $allowedValues;
/**
* Creates new instance of the class.
*
@@ -56,6 +57,24 @@ public function __construct(string $varName) {
$this->isOptional = false;
}
$this->name = trim($trimmed, '?');
+ $this->allowedValues = [];
+ }
+ public function addAllowedValues(array $vals) : UriParameter {
+ foreach ($vals as $val) {
+ $this->addAllowedValue($val);
+ }
+ return $this;
+ }
+ public function addAllowedValue(string $val) : UriParameter {
+ $this->allowedValues[] = trim($val);
+ $currentVal = $this->getValue();
+ if ($currentVal !== null && !in_array($currentVal, $this->allowedValues)) {
+ $this->value = null;
+ }
+ return $this;
+ }
+ public function getAllowedValues() : array {
+ return $this->allowedValues;
}
/**
* Returns the name of the parameter.
@@ -71,7 +90,7 @@ public function getName() : string {
* @return string|null If the value of the parameter is set, it will
* be returned as string. If not set, null is returned.
*/
- public function getValue() {
+ public function getValue() : ?string {
return $this->value;
}
/**
@@ -85,9 +104,21 @@ public function isOptional() : bool {
/**
* Sets the value of the parameter.
*
+ * Note that if the parameter has a set of allowed values, the method
+ * will only accept the value if its part if that set.
+ *
* @param string $val The value of the parameter as string.
*/
- public function setValue(string $val) {
- $this->value = $val;
+ public function setValue(string $val) : bool {
+ $allowed = $this->getAllowedValues();
+ $trimmed = trim($val);
+ if (count($allowed) > 0 && !in_array($trimmed, $allowed)) {
+ return false;
+ }
+ if ($trimmed != '') {
+ $this->value = $trimmed;
+ return true;
+ }
+ return false;
}
}
diff --git a/WebFiori/Http/WebServicesManager.php b/WebFiori/Http/WebServicesManager.php
index bd08008b..7315dd17 100644
--- a/WebFiori/Http/WebServicesManager.php
+++ b/WebFiori/Http/WebServicesManager.php
@@ -2,7 +2,7 @@
/**
* This file is licensed under MIT License.
*
- * Copyright (c) 2019 Ibrahim BinAlshikh
+ * Copyright (c) 2019 WebFiori Framework
*
* For more information on the license, please visit:
* https://github.com/WebFiori/http/blob/master/LICENSE
@@ -24,16 +24,6 @@
*
*/
class WebServicesManager implements JsonI {
- /**
- * A constant which is used to indicate that the message that will be
- * sent is of type error
- */
- const E = 'error';
- /**
- * A constant which is used to indicate that the message that will be
- * sent is of type info
- */
- const I = 'info';
/**
* An array that contains the supported 'POST' request content types.
*
@@ -106,6 +96,7 @@ class WebServicesManager implements JsonI {
*
*/
private $services;
+ private $request;
/**
* Creates new instance of the class.
*
@@ -124,7 +115,7 @@ class WebServicesManager implements JsonI {
* number must follow the format 'X.X.X' where 'X' is a number between
* 0 and 9 inclusive.
*/
- public function __construct(string $version = '1.0.0') {
+ public function __construct(?Request $request = null, string $version = '1.0.0') {
$this->setVersion($version);
$this->setDescription('NO DESCRIPTION');
@@ -132,6 +123,11 @@ public function __construct(string $version = '1.0.0') {
$this->services = [];
$this->invParamsArr = [];
$this->missingParamsArr = [];
+ $this->request = $request ?? Request::createFromGlobals();
+ }
+ public function setRequest(Request $request) : WebServicesManager {
+ $this->request = $request;
+ return $this;
}
/**
* Adds new web service to the set of web services.
@@ -140,8 +136,8 @@ public function __construct(string $version = '1.0.0') {
*
*
*/
- public function addService(AbstractWebService $service) {
- $this->addAction($service);
+ public function addService(AbstractWebService $service) : WebServicesManager {
+ return $this->addAction($service);
}
/**
* Sends a response message to indicate that request content type is
@@ -164,7 +160,7 @@ public function addService(AbstractWebService $service) {
public function contentTypeNotSupported(string $cType = '') {
$j = new Json();
$j->add('request-content-type', $cType);
- $this->sendResponse(ResponseMessage::get('415'), self::E, 415,$j);
+ $this->sendResponse(ResponseMessage::get('415'), 415, AbstractWebService::E, $j);
}
/**
* Returns the name of the service which is being called.
@@ -331,10 +327,13 @@ public function invParams() {
}
$i++;
}
- $this->sendResponse(ResponseMessage::get('404-1').$val.'.', self::E, 404, new Json([
+ $this->sendResponse(ResponseMessage::get('404-1').$val.'.', 404, AbstractWebService::E, new Json([
'invalid' => $paramsNamesArr
]));
}
+ public function getRequest() : Request {
+ return $this->request;
+ }
/**
* Checks if request content type is supported by the service or not (For 'POST'
* and PUT requests only).
@@ -346,8 +345,8 @@ public function invParams() {
*
*/
public final function isContentTypeSupported() : bool {
- $c = Request::getContentType();
- $rm = Request::getMethod();
+ $c = $this->getRequest()->getContentType();
+ $rm = $this->getRequest()->getMethod();
if ($c !== null && ($rm == RequestMethod::POST || $rm == RequestMethod::PUT)) {
return in_array($c, self::POST_CONTENT_TYPES);
@@ -384,7 +383,7 @@ public function missingParams() {
}
$i++;
}
- $this->sendResponse(ResponseMessage::get('404-2').$val.'.', self::E, 404, new Json([
+ $this->sendResponse(ResponseMessage::get('404-2').$val.'.', 404, AbstractWebService::E, new Json([
'missing' => $paramsNamesArr
]));
}
@@ -403,7 +402,7 @@ public function missingParams() {
*
*/
public function missingServiceName() {
- $this->sendResponse(ResponseMessage::get('404-3'), self::E, 404);
+ $this->sendResponse(ResponseMessage::get('404-3'), 404, AbstractWebService::E);
}
/**
* Sends a response message to indicate that a user is not authorized call a
@@ -420,7 +419,7 @@ public function missingServiceName() {
*
*/
public function notAuth() {
- $this->sendResponse(ResponseMessage::get('401'), self::E, 401);
+ $this->sendResponse(ResponseMessage::get('401'), 401, AbstractWebService::E);
}
/**
@@ -455,7 +454,7 @@ public final function process() {
}
}
} else {
- $c = Request::getContentType();
+ $c = $this->getRequest()->getContentType();
if ($c === null) {
$c = 'NOT_SET';
@@ -528,7 +527,7 @@ public function removeServices() {
*
*/
public function requestMethodNotAllowed() {
- $this->sendResponse(ResponseMessage::get('405'), self::E, 405);
+ $this->sendResponse(ResponseMessage::get('405'), 405, AbstractWebService::E);
}
/**
* Sends Back a data using specific content type and specific response code.
@@ -592,7 +591,7 @@ public function sendHeaders(array $headersArr) {
* will be not included in response. Default is empty string. Default is null.
*
*/
- public function sendResponse(string $message, string $type = '', int $code = 200, mixed $otherInfo = '') {
+ public function sendResponse(string $message, int $code = 200, string $type = '', mixed $otherInfo = '') {
$json = new Json();
$json->add('message', $message);
$typeTrimmed = trim($type);
@@ -632,7 +631,7 @@ public function sendResponse(string $message, string $type = '', int $code = 200
*
*/
public function serviceNotImplemented() {
- $this->sendResponse(ResponseMessage::get('404-4'), self::E, 404);
+ $this->sendResponse(ResponseMessage::get('404-4'), 404, AbstractWebService::E);
}
/**
* Sends a response message to indicate that called web service is not supported by the API.
@@ -648,7 +647,7 @@ public function serviceNotImplemented() {
*
*/
public function serviceNotSupported() {
- $this->sendResponse(ResponseMessage::get('404-5'), self::E, 404);
+ $this->sendResponse(ResponseMessage::get('404-5'), 404, AbstractWebService::E);
}
/**
* Sets the description of the web services set.
@@ -821,7 +820,7 @@ private function _checkAction(): bool {
$allowedMethods = $calledService->getRequestMethods();
if (count($allowedMethods) != 0) {
- $isValidRequestMethod = in_array(Request::getMethod(), $allowedMethods);
+ $isValidRequestMethod = in_array($this->getRequest()->getMethod(), $allowedMethods);
if (!$isValidRequestMethod) {
$this->requestMethodNotAllowed();
@@ -829,7 +828,7 @@ private function _checkAction(): bool {
return true;
}
} else {
- $this->sendResponse(ResponseMessage::get('404-6'), self::E, 404);
+ $this->sendResponse(ResponseMessage::get('404-6'), 404, AbstractWebService::E);
}
} else {
$this->serviceNotSupported();
@@ -883,17 +882,18 @@ private function _processNonJson($params) {
*
* @deprecated since version 1.4.7 Use WebservicesSet::addService()
*/
- private function addAction(AbstractWebService $service) {
+ private function addAction(AbstractWebService $service) : WebServicesManager {
$this->services[$service->getName()] = $service;
$service->setManager($this);
+ return $this;
}
/**
* @throws Exception
*/
private function filterInputsHelper() {
- $reqMeth = Request::getMethod();
- $contentType = Request::getContentType();
+ $reqMeth = $this->getRequest()->getMethod();
+ $contentType = $this->getRequest()->getContentType();
if ($reqMeth == RequestMethod::GET ||
$reqMeth == RequestMethod::DELETE ||
@@ -919,11 +919,11 @@ private function filterInputsHelper() {
* @deprecated since version 1.4.6 Use WebServicesManager::getCalledServiceName() instead.
*/
private function getAction() {
- $reqMeth = Request::getMethod();
+ $reqMeth = $this->getRequest()->getMethod();
$serviceIdx = ['action','service', 'service-name'];
- $contentType = Request::getContentType();
+ $contentType = $this->getRequest()->getContentType();
$retVal = null;
if ($contentType == 'application/json') {
@@ -963,7 +963,7 @@ private function getAction() {
}
private function isAuth(AbstractWebService $service) {
if ($service->isAuthRequired()) {
- $isAuthCheck = 'isAuthorized'.Request::getMethod();
+ $isAuthCheck = 'isAuthorized'.$this->getRequest()->getMethod();
if (!method_exists($service, $isAuthCheck)) {
return $service->isAuthorized() === null || $service->isAuthorized();
@@ -975,7 +975,7 @@ private function isAuth(AbstractWebService $service) {
return true;
}
private function processService(AbstractWebService $service) {
- $processMethod = 'process'.Request::getMethod();
+ $processMethod = 'process'.$this->getRequest()->getMethod();
if (!method_exists($service, $processMethod)) {
$service->processRequest();
diff --git a/composer.json b/composer.json
index 5ab400fb..fbc4a390 100644
--- a/composer.json
+++ b/composer.json
@@ -32,7 +32,7 @@
},
"scripts": {
"test": "phpunit --configuration tests/phpunit.xml",
- "test-10": "phpunit --configuration tests/phpunit10.xml"
+ "test10": "phpunit --configuration tests/phpunit10.xml"
},
"require-dev": {
"phpunit/phpunit": "^10.0"
diff --git a/tests/WebFiori/Tests/Http/HttpCookieTest.php b/tests/WebFiori/Tests/Http/HttpCookieTest.php
index 518b1129..4e8402a8 100644
--- a/tests/WebFiori/Tests/Http/HttpCookieTest.php
+++ b/tests/WebFiori/Tests/Http/HttpCookieTest.php
@@ -70,12 +70,12 @@ public function testConstructor03() {
$this->assertEquals('/', $cookie->getPath());
$this->assertEquals('', $cookie->getLifetime());
$this->assertEquals('Lax', $cookie->getSameSite());
- $this->assertEquals('127.0.0.1', $cookie->getDomain());
+ $this->assertNull($cookie->getDomain());
$cookie->setValue('super');
$this->assertEquals('super', $cookie->getValue());
$cookie->setIsHttpOnly(false);
$this->assertFalse($cookie->isHttpOnly());
- $this->assertEquals('new-cookie=super; domain=127.0.0.1; path=/; Secure; SameSite=Lax', $cookie->getHeaderString());
+ $this->assertEquals('new-cookie=super; path=/; Secure; SameSite=Lax', $cookie->getHeaderString());
$cookie->setIsSecure(false);
$this->assertFalse($cookie->isSecure());
$cookie->setDomain();
diff --git a/tests/WebFiori/Tests/Http/HttpMessageTest.php b/tests/WebFiori/Tests/Http/HttpMessageTest.php
new file mode 100644
index 00000000..1ee91cdd
--- /dev/null
+++ b/tests/WebFiori/Tests/Http/HttpMessageTest.php
@@ -0,0 +1,184 @@
+message = new HttpMessage();
+ }
+
+ /**
+ * @test
+ */
+ public function testConstructor() {
+ $message = new HttpMessage();
+ $this->assertInstanceOf(HeadersPool::class, $message->getHeadersPool());
+ }
+
+ /**
+ * @test
+ */
+ public function testGetHeadersPool() {
+ $pool = $this->message->getHeadersPool();
+ $this->assertInstanceOf(HeadersPool::class, $pool);
+ }
+
+ /**
+ * @test
+ */
+ public function testAddHeader() {
+ $result = $this->message->addHeader('Content-Type', 'application/json');
+ $this->assertTrue($result);
+
+ $headers = $this->message->getHeaders();
+ $this->assertCount(1, $headers);
+ $this->assertEquals('content-type', $headers[0]->getName());
+ $this->assertEquals('application/json', $headers[0]->getValue());
+ }
+
+ /**
+ * @test
+ */
+ public function testAddInvalidHeader() {
+ $result = $this->message->addHeader('Invalid Header Name', 'value');
+ $this->assertFalse($result);
+ }
+
+ /**
+ * @test
+ */
+ public function testGetHeader() {
+ $this->message->addHeader('Content-Type', 'application/json');
+
+ $values = $this->message->getHeader('content-type');
+ $this->assertEquals(['application/json'], $values);
+
+ $empty = $this->message->getHeader('non-existent');
+ $this->assertEquals([], $empty);
+ }
+
+ /**
+ * @test
+ */
+ public function testGetHeaders() {
+ $this->assertEquals([], $this->message->getHeaders());
+
+ $this->message->addHeader('Content-Type', 'application/json');
+ $this->message->addHeader('Accept', 'text/html');
+
+ $headers = $this->message->getHeaders();
+ $this->assertCount(2, $headers);
+ }
+
+ /**
+ * @test
+ */
+ public function testHasHeader() {
+ $this->assertFalse($this->message->hasHeader('Content-Type'));
+
+ $this->message->addHeader('Content-Type', 'application/json');
+
+ $this->assertTrue($this->message->hasHeader('Content-Type'));
+ $this->assertTrue($this->message->hasHeader('content-type'));
+ $this->assertTrue($this->message->hasHeader('Content-Type', 'application/json'));
+ $this->assertFalse($this->message->hasHeader('Content-Type', 'text/html'));
+ }
+
+ /**
+ * @test
+ */
+ public function testRemoveHeader() {
+ $this->message->addHeader('Content-Type', 'application/json');
+ $this->message->addHeader('Accept', 'text/html');
+
+ $this->assertTrue($this->message->hasHeader('Content-Type'));
+
+ $result = $this->message->removeHeader('Content-Type');
+ $this->assertTrue($result);
+ $this->assertFalse($this->message->hasHeader('Content-Type'));
+ $this->assertTrue($this->message->hasHeader('Accept'));
+
+ $result = $this->message->removeHeader('non-existent');
+ $this->assertFalse($result);
+ }
+
+ /**
+ * @test
+ */
+ public function testRemoveHeaderWithValue() {
+ $this->message->addHeader('Accept', 'application/json');
+ $this->message->addHeader('Accept', 'text/html');
+
+ $result = $this->message->removeHeader('Accept', 'application/json');
+ $this->assertTrue($result);
+
+ $values = $this->message->getHeader('Accept');
+ $this->assertEquals(['text/html'], $values);
+ }
+
+ /**
+ * @test
+ */
+ public function testMultipleHeaderValues() {
+ $this->message->addHeader('Accept', 'application/json');
+ $this->message->addHeader('Accept', 'text/html');
+
+ $values = $this->message->getHeader('Accept');
+ $this->assertCount(2, $values);
+ $this->assertContains('application/json', $values);
+ $this->assertContains('text/html', $values);
+ }
+
+ /**
+ * @test
+ */
+ public function testReplaceHeaderValue() {
+ $this->message->addHeader('Content-Type', 'text/plain');
+ $this->message->addHeader('Content-Type', 'application/json', 'text/plain');
+
+ $values = $this->message->getHeader('Content-Type');
+ $this->assertEquals(['application/json'], $values);
+ }
+
+ /**
+ * @test
+ */
+ public function testCaseInsensitiveHeaders() {
+ $this->message->addHeader('Content-Type', 'application/json');
+
+ $this->assertTrue($this->message->hasHeader('content-type'));
+ $this->assertTrue($this->message->hasHeader('CONTENT-TYPE'));
+ $this->assertTrue($this->message->hasHeader('Content-Type'));
+
+ $values = $this->message->getHeader('CONTENT-TYPE');
+ $this->assertEquals(['application/json'], $values);
+ }
+
+ /**
+ * @test
+ */
+ public function testMultipleInstances() {
+ $message1 = new HttpMessage();
+ $message2 = new HttpMessage();
+
+ $message1->addHeader('Content-Type', 'application/json');
+ $message2->addHeader('Accept', 'text/html');
+
+ $this->assertTrue($message1->hasHeader('Content-Type'));
+ $this->assertFalse($message1->hasHeader('Accept'));
+
+ $this->assertTrue($message2->hasHeader('Accept'));
+ $this->assertFalse($message2->hasHeader('Content-Type'));
+ }
+}
diff --git a/tests/WebFiori/Tests/Http/RequestTest.php b/tests/WebFiori/Tests/Http/RequestTest.php
index 5dc11fea..91abc0c3 100644
--- a/tests/WebFiori/Tests/Http/RequestTest.php
+++ b/tests/WebFiori/Tests/Http/RequestTest.php
@@ -1,19 +1,22 @@
assertNull(Request::getParam('not-exist'));
+ $this->request = Request::createFromGlobals();
+ $this->assertNull($this->request->getParam('not-exist'));
}
/**
* @test
@@ -22,7 +25,8 @@ public function testGetParam01() {
putenv('REQUEST_METHOD=POST');
$_SERVER['CONTENT_TYPE'] = 'multipart/form-data';
$_POST['ok'] = 'I Ok';
- $this->assertEquals('I Ok', Request::getParam('ok'));
+ $this->request = Request::createFromGlobals();
+ $this->assertEquals('I Ok', $this->request->getParam('ok'));
}
/**
* @test
@@ -30,7 +34,8 @@ public function testGetParam01() {
public function testGetParam02() {
putenv('REQUEST_METHOD=GET');
$_GET['ok'] = 'I not Ok';
- $this->assertEquals('I not Ok', Request::getParam('ok'));
+ $this->request = Request::createFromGlobals();
+ $this->assertEquals('I not Ok', $this->request->getParam('ok'));
$_GET = [];
}
/**
@@ -38,14 +43,16 @@ public function testGetParam02() {
*/
public function testGetParam03() {
putenv('REQUEST_METHOD=POST');
- $this->assertNull(Request::getParam('not-exist'));
+ $this->request = Request::createFromGlobals();
+ $this->assertNull($this->request->getParam('not-exist'));
}
/**
* @test
*/
public function testGetParam04() {
putenv('REQUEST_METHOD=GET');
- $this->assertNull(Request::getParam('not-exist'));
+ $this->request = Request::createFromGlobals();
+ $this->assertNull($this->request->getParam('not-exist'));
}
/**
* @test
@@ -53,7 +60,8 @@ public function testGetParam04() {
public function testGetParam05() {
putenv('REQUEST_METHOD=GET');
$_GET['hello'] = 'This%20is%20an%20encoded%20string.';
- $this->assertEquals('This is an encoded string.', Request::getParam('hello'));
+ $this->request = Request::createFromGlobals();
+ $this->assertEquals('This is an encoded string.', $this->request->getParam('hello'));
$_GET = [];
}
/**
@@ -62,7 +70,8 @@ public function testGetParam05() {
public function testGetParam06() {
putenv('REQUEST_METHOD=GET');
$_GET['hello'] = 'This+is+an+encoded%20string.';
- $this->assertEquals('This is an encoded string.', Request::getParam('hello'));
+ $this->request = Request::createFromGlobals();
+ $this->assertEquals('This is an encoded string.', $this->request->getParam('hello'));
$_GET = [];
}
/**
@@ -71,42 +80,49 @@ public function testGetParam06() {
public function testGetParams06() {
putenv('REQUEST_METHOD=GET');
$_GET['arabic'] = '%D9%86%D8%B5%20%D8%B9%D8%B1%D8%A8%D9%8A';
- $this->assertEquals('نص عربي', Request::getParam('arabic'));
+ $this->request = Request::createFromGlobals();
+ $this->assertEquals('نص عربي', $this->request->getParam('arabic'));
$_GET = [];
}
/**
* @test
*/
public function testGetClientIp00() {
- $this->assertEquals('127.0.0.1', Request::getClientIP());
+ $this->request = Request::createFromGlobals();
+ $this->assertEquals('127.0.0.1', $this->request->getClientIP());
}
/**
* @test
*/
public function testGetClientIp01() {
$_SERVER['REMOTE_ADDR'] = '::1';
- $this->assertEquals('127.0.0.1', Request::getClientIP());
+ $this->request = Request::createFromGlobals();
+ $this->assertEquals('127.0.0.1', $this->request->getClientIP());
}
/**
* @test
*/
public function testGetClientIp02() {
$_SERVER['REMOTE_ADDR'] = '127.5.5.6';
- $this->assertEquals('127.5.5.6', Request::getClientIP());
+ $this->request = Request::createFromGlobals();
+ $this->assertEquals('127.5.5.6', $this->request->getClientIP());
}
/**
* @test
*/
public function testGetClientIp03() {
$_SERVER['REMOTE_ADDR'] = '127.5A.5.6';
- $this->assertEquals('', Request::getClientIP());
+ $this->request = Request::createFromGlobals();
+ $this->assertEquals('', $this->request->getClientIP());
}
/**
* @test
*/
public function testGetRequestedURL00() {
+ $_SERVER['HTTP_HOST'] = '127.0.0.1';
$_SERVER['PATH_INFO'] = '/my/app';
- $this->assertEquals('http://127.0.0.1/my/app', Request::getRequestedURI());
+ $this->request = Request::createFromGlobals();
+ $this->assertEquals('http://127.0.0.1/my/app', $this->request->getRequestedURI());
}
/**
* @test
@@ -115,7 +131,8 @@ public function testGetRequestedURL01() {
$_SERVER['PATH_INFO'] = '/my/app';
$_GET['param1'] = 'something';
$_GET['param2'] = 'something_else';
- $this->assertEquals('http://127.0.0.1/my/app?param1=something¶m2=something_else', Request::getRequestedURI());
+ $this->request = Request::createFromGlobals();
+ $this->assertEquals('http://127.0.0.1/my/app?param1=something¶m2=something_else', $this->request->getRequestedURI());
$_GET = [];
}
/**
@@ -123,7 +140,8 @@ public function testGetRequestedURL01() {
*/
public function testGetRequestedURL03() {
putenv('REQUEST_URI=/my/app/x');
- $this->assertEquals('http://127.0.0.1/my/app/x', Request::getRequestedURI());
+ $this->request = Request::createFromGlobals();
+ $this->assertEquals('http://127.0.0.1/my/app/x', $this->request->getRequestedURI());
}
/**
* @test
@@ -131,33 +149,49 @@ public function testGetRequestedURL03() {
public function testGetRequestedURL04() {
putenv('REQUEST_URI=/my/app/x?b=p');
$_GET['c'] = 'k';
- $this->assertEquals('http://127.0.0.1/my/app/x?c=k', Request::getRequestedURI());
+ $this->request = Request::createFromGlobals();
+ $this->assertEquals('http://127.0.0.1/my/app/x?c=k', $this->request->getRequestedURI());
$_GET = [];
}
/**
* @test
*/
public function testGetRequestedURL05() {
+ unset($_SERVER['PATH_INFO']);
putenv('REQUEST_URI');
putenv('HTTP_REQUEST_URI=/A/B/C');
- $this->assertEquals('http://127.0.0.1/A/B/C', Request::getRequestedURI());
+ $this->request = Request::createFromGlobals();
+ $this->assertEquals('http://127.0.0.1/A/B/C', $this->request->getRequestedURI());
}
/**
* @test
*/
public function testGetRequestedURL06() {
+ unset($_SERVER['PATH_INFO']);
putenv('REQUEST_URI');
putenv('HTTP_REQUEST_URI');
$_SERVER['HTTP_X_ORIGINAL_URL'] = 'https://example.com/a/good/boy';
- $this->assertEquals('http://127.0.0.1/a/good/boy', Request::getRequestedURI());
+ $this->request = Request::createFromGlobals();
+ $this->assertEquals('http://127.0.0.1/a/good/boy', $this->request->getRequestedURI());
unset($_SERVER['HTTP_X_ORIGINAL_URL']);
}
/**
* @test
*/
public function testGetHeaders00() {
+ // Store original state
+ $originalServer = $_SERVER;
+
+ // Clear HTTP headers from $_SERVER
+ foreach ($_SERVER as $key => $value) {
+ if (strpos($key, 'HTTP_') === 0) {
+ unset($_SERVER[$key]);
+ }
+ }
+
$_SERVER['HTTP_CONTENT_TYPE'] = "application/json";
$_SERVER['HTTP_X_HOST'] = "Custom H";
+ $this->request = Request::createFromGlobals();
$this->assertEquals([
'content-type' => [
'application/json'
@@ -165,14 +199,19 @@ public function testGetHeaders00() {
'x-host' => [
'Custom H'
]
- ], Request::getHeadersAssoc());
+ ], $this->request->getHeadersAssoc());
+
+ // Restore original state
+ $_SERVER = $originalServer;
}
/**
* @test
*/
public function testGetCookie00() {
- $this->assertNull(Request::getCookieValue('not-exist'));
+ $this->request = Request::createFromGlobals();
+ $this->assertNull($this->request->getCookieValue('not-exist'));
$_COOKIE['cool'] = 'cool_cookie';
- $this->assertEquals('cool_cookie', Request::getCookieValue('cool'));
+ $this->request = Request::createFromGlobals();
+ $this->assertEquals('cool_cookie', $this->request->getCookieValue('cool'));
}
}
diff --git a/tests/WebFiori/Tests/Http/RequestTest2.php b/tests/WebFiori/Tests/Http/RequestTest2.php
new file mode 100644
index 00000000..01f9ac84
--- /dev/null
+++ b/tests/WebFiori/Tests/Http/RequestTest2.php
@@ -0,0 +1,250 @@
+request = new Request();
+ }
+
+ /**
+ * @test
+ */
+ public function testExtendsHttpMessage() {
+ $this->assertInstanceOf(HttpMessage::class, $this->request);
+ }
+
+ /**
+ * @test
+ */
+ public function testCreateFromGlobals() {
+ putenv('REQUEST_METHOD=POST');
+ $_SERVER['HTTP_CONTENT_TYPE'] = 'application/json';
+
+ $request = Request::createFromGlobals();
+
+ $this->assertInstanceOf(Request::class, $request);
+ $this->assertEquals('POST', $request->getMethod());
+ }
+
+ /**
+ * @test
+ */
+ public function testGetMethod() {
+ $this->request->setRequestMethod('PUT');
+ $this->assertEquals('PUT', $this->request->getMethod());
+ }
+
+ /**
+ * @test
+ */
+ public function testGetClientIP() {
+ $_SERVER['REMOTE_ADDR'] = '192.168.1.100';
+ $this->assertEquals('192.168.1.100', $this->request->getClientIP());
+ }
+
+ /**
+ * @test
+ */
+ public function testGetClientIPDefault() {
+ unset($_SERVER['REMOTE_ADDR']);
+ $this->assertEquals('127.0.0.1', $this->request->getClientIP());
+ }
+
+ /**
+ * @test
+ */
+ public function testGetContentType() {
+ $_SERVER['CONTENT_TYPE'] = 'application/json';
+ $this->assertEquals('application/json', $this->request->getContentType());
+ }
+
+ /**
+ * @test
+ */
+ public function testGetContentTypeNull() {
+ unset($_SERVER['CONTENT_TYPE']);
+ $this->assertNull($this->request->getContentType());
+ }
+
+ /**
+ * @test
+ */
+ public function testGetParamFromGet() {
+ putenv('REQUEST_METHOD=GET');
+ $_GET['test_param'] = 'test_value';
+
+ $request = Request::createFromGlobals();
+ $this->assertEquals('test_value', $request->getParam('test_param'));
+ }
+
+ /**
+ * @test
+ */
+ public function testGetParamFromPost() {
+ putenv('REQUEST_METHOD=POST');
+ $_POST['test_param'] = 'post_value';
+
+ $request = Request::createFromGlobals();
+ $this->assertEquals('post_value', $request->getParam('test_param'));
+ }
+
+ /**
+ * @test
+ */
+ public function testGetParamNotExists() {
+ $this->assertNull($this->request->getParam('non_existent'));
+ }
+
+ /**
+ * @test
+ */
+ public function testGetParams() {
+ putenv('REQUEST_METHOD=GET');
+ $_GET['param1'] = 'value1';
+ $_GET['param2'] = 'value2';
+
+ $request = Request::createFromGlobals();
+ $params = $request->getParams();
+
+ $this->assertArrayHasKey('param1', $params);
+ $this->assertArrayHasKey('param2', $params);
+ $this->assertEquals('value1', $params['param1']);
+ $this->assertEquals('value2', $params['param2']);
+ }
+
+ /**
+ * @test
+ */
+ public function testGetCookieValue() {
+ $_COOKIE['test_cookie'] = 'cookie_value';
+ $this->assertEquals('cookie_value', $this->request->getCookieValue('test_cookie'));
+ }
+
+ /**
+ * @test
+ */
+ public function testGetCookieValueNotExists() {
+ $this->assertNull($this->request->getCookieValue('non_existent_cookie'));
+ }
+
+ /**
+ * @test
+ */
+ public function testGetPath() {
+ $_SERVER['REQUEST_URI'] = '/api/users?id=123';
+ $request = Request::createFromGlobals();
+ $this->assertEquals('/api/users', $request->getPath());
+ }
+
+ /**
+ * @test
+ */
+ public function testGetPathDefault() {
+ unset($_SERVER['REQUEST_URI']);
+ unset($_SERVER['PATH_INFO']);
+ unset($_SERVER['SCRIPT_NAME']);
+
+ $request = Request::createFromGlobals();
+ $this->assertEquals('/', $request->getPath());
+ }
+
+ /**
+ * @test
+ */
+ public function testGetRequestedURI() {
+ $_SERVER['REQUEST_URI'] = '/test';
+ $_SERVER['HTTP_HOST'] = 'example.com';
+
+ $request = Request::createFromGlobals();
+ $uri = $request->getRequestedURI();
+
+ $this->assertStringContainsString('/test', $uri);
+ }
+
+ /**
+ * @test
+ */
+ public function testGetRequestedURIWithAppend() {
+ $_SERVER['REQUEST_URI'] = '/api';
+ $_SERVER['HTTP_HOST'] = 'example.com';
+
+ $request = Request::createFromGlobals();
+ $uri = $request->getRequestedURI('users');
+
+ $this->assertStringContainsString('/api/users', $uri);
+ }
+
+ /**
+ * @test
+ */
+ public function testGetUri() {
+ $_SERVER['REQUEST_URI'] = '/test';
+ $_SERVER['HTTP_HOST'] = 'example.com';
+
+ $request = Request::createFromGlobals();
+ $uri = $request->getUri();
+
+ $this->assertInstanceOf(Uri::class, $uri);
+ }
+
+ /**
+ * @test
+ */
+ public function testGetAuthHeader() {
+ $this->request->addHeader('Authorization', 'Bearer token123');
+ $authHeader = $this->request->getAuthHeader();
+
+ $this->assertNotNull($authHeader);
+ $this->assertEquals('bearer', $authHeader->getScheme());
+ $this->assertEquals('token123', $authHeader->getCredentials());
+ }
+
+ /**
+ * @test
+ */
+ public function testGetAuthHeaderNotExists() {
+ $this->assertNull($this->request->getAuthHeader());
+ }
+
+ /**
+ * @test
+ */
+ public function testHeaderExtraction() {
+ $_SERVER['HTTP_CONTENT_TYPE'] = 'application/json';
+ $_SERVER['HTTP_X_CUSTOM_HEADER'] = 'custom_value';
+
+ $request = Request::createFromGlobals();
+
+ $this->assertTrue($request->hasHeader('content-type'));
+ $this->assertTrue($request->hasHeader('x-custom-header'));
+ $this->assertEquals(['application/json'], $request->getHeader('content-type'));
+ $this->assertEquals(['custom_value'], $request->getHeader('x-custom-header'));
+ }
+
+ /**
+ * @test
+ */
+ public function testMultipleInstances() {
+ $request1 = new Request();
+ $request2 = new Request();
+
+ $request1->addHeader('X-Test', 'value1');
+ $request2->addHeader('X-Test', 'value2');
+
+ $this->assertEquals(['value1'], $request1->getHeader('x-test'));
+ $this->assertEquals(['value2'], $request2->getHeader('x-test'));
+ }
+}
diff --git a/tests/WebFiori/Tests/Http/RequestUriTest.php b/tests/WebFiori/Tests/Http/RequestUriTest.php
new file mode 100644
index 00000000..6be29ab5
--- /dev/null
+++ b/tests/WebFiori/Tests/Http/RequestUriTest.php
@@ -0,0 +1,199 @@
+assertInstanceOf(Uri::class, $uri);
+ }
+
+ /**
+ * @test
+ */
+ public function testAddRequestMethod() {
+ $uri = new RequestUri('http://example.com');
+ $uri->addRequestMethod('get');
+ $uri->addRequestMethod('POST');
+
+ $methods = $uri->getRequestMethods();
+ $this->assertContains('GET', $methods);
+ $this->assertContains('POST', $methods);
+ }
+
+ /**
+ * @test
+ */
+ public function testSetRequestMethods() {
+ $uri = new RequestUri('http://example.com');
+ $uri->setRequestMethods(['get', 'post', 'put']);
+
+ $methods = $uri->getRequestMethods();
+ $this->assertEquals(['GET', 'POST', 'PUT'], $methods);
+ }
+
+ /**
+ * @test
+ */
+ public function testIsRequestMethodAllowed() {
+ $uri = new RequestUri('http://example.com');
+
+ // No methods set - should allow all
+ $this->assertTrue($uri->isRequestMethodAllowed('GET'));
+ $this->assertTrue($uri->isRequestMethodAllowed('post'));
+
+ // Set specific methods
+ $uri->setRequestMethods(['GET', 'POST']);
+ $this->assertTrue($uri->isRequestMethodAllowed('get'));
+ $this->assertTrue($uri->isRequestMethodAllowed('POST'));
+ $this->assertFalse($uri->isRequestMethodAllowed('put'));
+ $this->assertFalse($uri->isRequestMethodAllowed('DELETE'));
+ }
+
+ /**
+ * @test
+ */
+ public function testIsRequestMethodAllowedNormalization() {
+ $uri = new RequestUri('http://example.com');
+ $uri->addRequestMethod(' get ');
+
+ $this->assertTrue($uri->isRequestMethodAllowed('GET'));
+ $this->assertTrue($uri->isRequestMethodAllowed('get'));
+ $this->assertTrue($uri->isRequestMethodAllowed(' GET '));
+ }
+
+ /**
+ * @test
+ */
+ public function testHasParameters() {
+ $uri = new RequestUri('https://example.com/users/{id}');
+ $this->assertTrue($uri->hasParameters());
+
+ $uri2 = new RequestUri('https://example.com/users');
+ $this->assertFalse($uri2->hasParameters());
+ }
+
+ /**
+ * @test
+ */
+ public function testHasParameter() {
+ $uri = new RequestUri('https://example.com/users/{id}/posts/{postId}');
+ $this->assertTrue($uri->hasParameter('id'));
+ $this->assertTrue($uri->hasParameter('postId'));
+ $this->assertFalse($uri->hasParameter('name'));
+ }
+
+ /**
+ * @test
+ */
+ public function testGetParameter() {
+ $uri = new RequestUri('https://example.com/users/{id}');
+ $param = $uri->getParameter('id');
+
+ $this->assertNotNull($param);
+ $this->assertEquals('id', $param->getName());
+
+ $this->assertNull($uri->getParameter('nonexistent'));
+ }
+
+ /**
+ * @test
+ */
+ public function testSetParameterValue() {
+ $uri = new RequestUri('https://example.com/users/{id}');
+ $uri->setParameterValue('id', '123');
+
+ $param = $uri->getParameter('id');
+ $this->assertEquals('123', $param->getValue());
+ }
+
+ /**
+ * @test
+ */
+ public function testAddVarValue() {
+ $uri = new RequestUri('https://example.com/users/{id}');
+ $uri->addAllowedParameterValue('id', '123');
+
+ $param = $uri->getParameter('id');
+ $this->assertTrue($param instanceof UriParameter);
+
+ $this->assertEquals(['123'], $param->getAllowedValues());
+ $this->assertNull($param->getValue());
+
+ $this->assertFalse($param->setValue('132'));
+ $this->assertNull($param->getValue());
+
+ $this->assertTrue($param->setValue('123'));
+ $this->assertEquals('123', $param->getValue());
+ }
+
+ /**
+ * @test
+ */
+ public function testEquals() {
+ $uri1 = new RequestUri('https://example.com/users/{id}');
+ $uri1->setRequestMethods(['GET', 'POST']);
+
+ $uri2 = new RequestUri('https://example.com/users/{id}');
+ $uri2->setRequestMethods(['GET', 'POST']);
+
+ $uri3 = new RequestUri('https://example.com/users/{name}');
+ $uri3->setRequestMethods(['GET', 'POST']);
+
+ $this->assertTrue($uri1->equals($uri2));
+ $this->assertFalse($uri1->equals($uri3));
+ }
+
+ /**
+ * @test
+ */
+ public function testIsAllParametersSet() {
+ $uri = new RequestUri('https://example.com/users/{id}/posts/{postId}');
+ $this->assertFalse($uri->isAllParametersSet());
+
+ $uri->setParameterValue('id', '123');
+ $this->assertFalse($uri->isAllParametersSet());
+
+ $uri->setParameterValue('postId', '456');
+ $this->assertTrue($uri->isAllParametersSet());
+ }
+
+ /**
+ * @test
+ */
+ public function testGetParameterValues() {
+ $uri = new RequestUri('https://example.com/users/{id}/posts/{postId}');
+ $uri->setParameterValue('id', '123');
+ $uri->setParameterValue('postId', '789');
+
+ $value0 = $uri->getParameterValue('id');
+ $value1 = $uri->getParameterValue('postId');
+ $this->assertEquals('123', $value0);
+ $this->assertEquals('789', $value1);
+ }
+ /**
+ * @test
+ */
+ public function testSetUriPossibleVar03() {
+ $uri = new RequestUri('https://example.com/{first-var}/ok/{second-var}');
+ $uri->addAllowedParameterValues('first-var', ['Hello','World'])
+ ->addAllowedParameterValues(' second-var ', ['hell','is','not','heven'])
+ ->addAllowedParameterValues(' secohhnd-var ', ['hell','is']);
+ $this->assertEquals(['Hello','World'], $uri->getAllowedParameterValues('first-var'));
+ $this->assertEquals(['hell','is','not','heven'], $uri->getAllowedParameterValues('second-var'));
+ $this->assertEquals([], $uri->getAllowedParameterValues('secohhnd-var'));
+ }
+}
diff --git a/tests/WebFiori/Tests/Http/TestServices/GetUserProfileService.php b/tests/WebFiori/Tests/Http/TestServices/GetUserProfileService.php
index d0fb0709..eef1c240 100644
--- a/tests/WebFiori/Tests/Http/TestServices/GetUserProfileService.php
+++ b/tests/WebFiori/Tests/Http/TestServices/GetUserProfileService.php
@@ -20,7 +20,7 @@ public function __construct() {
public function processRequest() {
$userId = $this->getParamVal('user-id');
if ($userId === null || $userId < 0) {
- $this->getManager()->sendResponse('Database Error.', self::E, 500);
+ $this->sendResponse('Database Error.', 500, self::E);
} else {
$j = new Json();
$j->add('user-name', 'Ibrahim');
diff --git a/tests/WebFiori/Tests/Http/UriTest.php b/tests/WebFiori/Tests/Http/UriTest.php
index 6d159f9d..2a2ba9b6 100644
--- a/tests/WebFiori/Tests/Http/UriTest.php
+++ b/tests/WebFiori/Tests/Http/UriTest.php
@@ -1,8 +1,12 @@
assertEquals([], $uri->getRequestMethods());
$this->assertTrue($uri->isRequestMethodAllowed());
$uri->addRequestMethod('GET');
@@ -25,8 +29,8 @@ public function testAllowedRequestMethods00() {
*/
public function testAllowedRequestMethods01() {
putenv('REQUEST_METHOD=GET');
- $uri = new Uri('https://example.com/');
- $uri->setRequestMethods(['POST', 'PUT', 'Get']);
+ $uri = new RequestUri('https://example.com/');
+ $uri->setRequestMethods(['POST', 'PUT']);
$this->assertEquals(['POST', 'PUT'], $uri->getRequestMethods());
$this->assertFalse($uri->isRequestMethodAllowed());
putenv('REQUEST_METHOD=PUT');
@@ -36,9 +40,9 @@ public function testAllowedRequestMethods01() {
* @test
*/
public function testSetUriPossibleVar00() {
- $uri = new Uri('https://example.com/{first-var}');
- $uri->addVarValue('first-var', 'Hello World');
- $this->assertEquals(['Hello World'], $uri->getParameterValues('first-var'));
+ $uri = new RequestUri('https://example.com/{first-var}');
+ $uri->addAllowedParameterValue('first-var', 'Hello World');
+ $this->assertEquals(['Hello World'], $uri->getAllowedParameterValues('first-var'));
$this->assertEquals('/{first-var}', $uri->getPath());
$this->assertEquals(['{first-var}'], $uri->getPathArray());
}
@@ -46,23 +50,23 @@ public function testSetUriPossibleVar00() {
* @test
*/
public function testSetUriPossibleVar01() {
- $uri = new Uri('https://example.com/{first-var}');
- $uri->addVarValue(' first-var ', ' Hello World ');
- $this->assertEquals(['Hello World'], $uri->getParameterValues('first-var'));
+ $uri = new RequestUri('https://example.com/{first-var}');
+ $uri->addAllowedParameterValue(' first-var ', ' Hello World ');
+ $this->assertEquals(['Hello World'], $uri->getAllowedParameterValues('first-var'));
}
/**
* @test
*/
public function testSetUriPossibleVar02() {
- $uri = new Uri('https://example.com/{first-var}');
- $uri->addVarValues('first-var', ['Hello','World']);
- $this->assertEquals(['Hello','World'], $uri->getParameterValues('first-var'));
+ $uri = new RequestUri('https://example.com/{first-var}');
+ $uri->addAllowedParameterValues('first-var', ['Hello','World']);
+ $this->assertEquals(['Hello','World'], $uri->getAllowedParameterValues('first-var'));
}
/**
* @test
*/
public function testParams00() {
- $uri = new Uri('https://example.com/{first-var}');
+ $uri = new RequestUri('https://example.com/{first-var}');
$this->assertTrue($uri->hasParameter('first-var'));
$this->assertFalse($uri->getParameter('first-var')->isOptional());
$this->assertNull($uri->getParameter('first-var')->getValue());
@@ -75,7 +79,7 @@ public function testParams00() {
* @test
*/
public function testParams01() {
- $uri = new Uri('https://example.com/{first-var?}');
+ $uri = new RequestUri('https://example.com/{first-var?}');
$this->assertEquals('/{first-var?}', $uri->getPath());
$this->assertTrue($uri->hasParameter('first-var'));
$this->assertTrue($uri->getParameter('first-var')->isOptional());
@@ -85,39 +89,29 @@ public function testParams01() {
$this->assertEquals('1009', $uri->getParameter('first-var')->getValue());
$this->assertFalse($uri->setParameterValue('not-exist', 'hello'));
}
- /**
- * @test
- */
- public function testSetUriPossibleVar03() {
- $uri = new Uri('https://example.com/{first-var}/ok/{second-var}');
- $uri->addVarValues('first-var', ['Hello','World']);
- $uri->addVarValues(' second-var ', ['hell','is','not','heven']);
- $uri->addVarValues(' secohhnd-var ', ['hell','is']);
- $this->assertEquals(['Hello','World'], $uri->getParameterValues('first-var'));
- $this->assertEquals(['hell','is','not','heven'], $uri->getParameterValues('second-var'));
- $this->assertEquals([], $uri->getParameterValues('secohhnd-var'));
- }
+
/**
* @test
*/
public function testSetUriPossibleVar04() {
$this->expectException('Exception');
- $this->expectExceptionMessage('Incorrect parameters order.');
- $uri = new Uri('https://example.com/{first-var}/ok/{second-var?}/{non-optional}');
+ $this->expectExceptionMessage('Requred paramater cannot appear after optional');
+ $uri = new RequestUri('https://example.com/{first-var}/ok/{second-var?}/{non-optional}');
}
/**
* @test
*/
public function testInvalid00() {
- $this->expectException('Exception');
- $uri = new Uri('');
+ $this->expectException(InvalidArgumentException::class);
+ $this->expectExceptionMessage('URI must be non-empty string');
+ $uri = new RequestUri('');
}
/**
* @test
*/
public function testEquals00() {
- $uri1 = new Uri('https://example.com/my-folder');
- $uri2 = new Uri('https://example.com/my-folder');
+ $uri1 = new RequestUri('https://example.com/my-folder');
+ $uri2 = new RequestUri('https://example.com/my-folder');
$this->assertTrue($uri1->equals($uri2));
$this->assertTrue($uri2->equals($uri1));
}
@@ -125,8 +119,8 @@ public function testEquals00() {
* @test
*/
public function testEquals01() {
- $uri1 = new Uri('https://example.com:80/my-folder');
- $uri2 = new Uri('https://example.com/my-folder');
+ $uri1 = new RequestUri('https://example.com:80/my-folder');
+ $uri2 = new RequestUri('https://example.com/my-folder');
$this->assertFalse($uri1->equals($uri2));
$this->assertFalse($uri2->equals($uri1));
}
@@ -134,8 +128,8 @@ public function testEquals01() {
* @test
*/
public function testEquals02() {
- $uri1 = new Uri('http://example.com/my-folder-2');
- $uri2 = new Uri('https://example.com/my-folder');
+ $uri1 = new RequestUri('http://example.com/my-folder-2');
+ $uri2 = new RequestUri('https://example.com/my-folder');
$this->assertFalse($uri1->equals($uri2));
$this->assertFalse($uri2->equals($uri1));
}
@@ -143,17 +137,26 @@ public function testEquals02() {
* @test
*/
public function testEquals03() {
- $uri1 = new Uri('http://example.com/my-folder');
- $uri2 = new Uri('https://example.com/my-folder');
- $this->assertTrue($uri1->equals($uri2));
- $this->assertTrue($uri2->equals($uri1));
+ $uri1 = new RequestUri('http://example.com/my-folder');
+ $uri2 = new RequestUri('https://example.com/my-folder');
+ $this->assertFalse($uri1->equals($uri2));
+ $this->assertFalse($uri2->equals($uri1));
}
/**
* @test
*/
public function testEquals04() {
- $uri1 = new Uri('http://example.com/my-folder/{a-var}');
- $uri2 = new Uri('https://example.com/my-folder/{a-var}');
+ $uri1 = new RequestUri('http://example.com/my-folder/{a-var}');
+ $uri2 = new RequestUri('https://example.com/my-folder/{a-var}');
+ $this->assertFalse($uri1->equals($uri2));
+ $this->assertFalse($uri2->equals($uri1));
+ }
+ /**
+ * @test
+ */
+ public function testEquals05() {
+ $uri1 = new RequestUri('https://example.com/my-folder/{a-var}');
+ $uri2 = new RequestUri('https://example.com/my-folder/{a-var}');
$this->assertTrue($uri1->equals($uri2));
$this->assertTrue($uri2->equals($uri1));
}
@@ -161,6 +164,8 @@ public function testEquals04() {
* @test
*/
public function testGetBase00() {
+ $_SERVER['HTTP_HOST'] = '127.0.0.1';
+ $request = Request::createFromGlobals();
$this->assertEquals('http://127.0.0.1', Uri::getBaseURL());
}
/**
@@ -168,7 +173,7 @@ public function testGetBase00() {
*/
public function testGetBase01() {
$_SERVER['HTTP_HOST'] = 'webfiori.com';
- $this->assertEquals('http://webfiori.com', Uri::getBaseURL());
+ $this->assertEquals('http://webfiori.com', RequestUri::getBaseURL());
}
/**
* @test
@@ -177,7 +182,7 @@ public function testGetBase03() {
$_SERVER['HTTP_HOST'] = 'webfiori.com';
$_SERVER['DOCUMENT_ROOT'] = __DIR__;
define('WF_PATH_TO_APPEND', 'my-app');
- $this->assertEquals('http://webfiori.com/my-app', Uri::getBaseURL());
+ $this->assertEquals('http://webfiori.com/my-app', RequestUri::getBaseURL());
}
/**
* @test
@@ -186,7 +191,7 @@ public function testGetBase04() {
$_SERVER['HTTP_HOST'] = 'webfiori.com';
$_SERVER['DOCUMENT_ROOT'] = __DIR__;
$_SERVER['HTTPS'] = 'HTTPS';
- $this->assertEquals('https://webfiori.com/my-app', Uri::getBaseURL());
+ $this->assertEquals('https://webfiori.com/my-app', RequestUri::getBaseURL());
}
/**
* @test
@@ -196,13 +201,13 @@ public function testGetBase02() {
$_SERVER['DOCUMENT_ROOT'] = __DIR__;
$_SERVER['HTTPS'] = null;
define('WF_PATH_TO_REMOVE', 'my-app');
- $this->assertEquals('http://webfiori.com/my-app', Uri::getBaseURL());
+ $this->assertEquals('http://webfiori.com/my-app', RequestUri::getBaseURL());
}
/**
* @test
*/
public function testGetComponents() {
- $uri = new Uri('https://example.com:8080/hell?me=ibrahim#22');
+ $uri = new RequestUri('https://example.com:8080/hell?me=ibrahim#22');
$components = $uri->getComponents();
$this->assertEquals('https://example.com:8080/hell?me=ibrahim#22', $components['uri']);
$this->assertEquals('https',$components['scheme']);
@@ -217,8 +222,8 @@ public function testGetComponents() {
* @test
*/
public function testEquals06() {
- $uri1 = new Uri('http://example.com/my-Folder/{a-var}', false);
- $uri2 = new Uri('https://example.com/my-folder/{a-var}', false);
+ $uri1 = new RequestUri('http://example.com/my-Folder/{a-var}', false);
+ $uri2 = new RequestUri('https://example.com/my-folder/{a-var}', false);
$this->assertFalse($uri1->equals($uri2));
$this->assertFalse($uri2->equals($uri1));
}
@@ -227,7 +232,7 @@ public function testEquals06() {
*/
public function testSplitURI_02() {
$uri = 'https://www3.programmingacademia.com:80/{some-var}/hell/{other-var}/?do=dnt&y=#xyz';
- $uriObj = new Uri($uri);
+ $uriObj = new RequestUri($uri);
$this->assertEquals('80',$uriObj->getPort());
}
/**
@@ -235,7 +240,7 @@ public function testSplitURI_02() {
*/
public function testSplitURI_03() {
$uri = 'https://www3.programmingacademia.com:80/{some-var}/hell/{other-var}/?do=dnt&y=#xyz';
- $uriObj = new Uri($uri);
+ $uriObj = new RequestUri($uri);
$this->assertEquals('xyz',$uriObj->getFragment());
}
/**
@@ -243,7 +248,7 @@ public function testSplitURI_03() {
*/
public function testSplitURI_04() {
$uri = 'https://www3.programmingacademia.com:80/{some-var}/hell/{other-var}/?do=dnt&y=#xyz';
- $uriObj = new Uri($uri);
+ $uriObj = new RequestUri($uri);
$this->assertEquals('do=dnt&y=',$uriObj->getQueryString());
}
/**
@@ -251,7 +256,7 @@ public function testSplitURI_04() {
*/
public function testSplitURI_05() {
$uri = 'https://www3.programmingacademia.com:80/{some-var}/hell/{other-var}/?do=dnt&y=#xyz';
- $uriObj = new Uri($uri);
+ $uriObj = new RequestUri($uri);
$this->assertEquals('https',$uriObj->getScheme());
}
/**
@@ -259,7 +264,7 @@ public function testSplitURI_05() {
*/
public function testSplitURI_06() {
$uri = 'https://www3.programmingacademia.com:80/{some-var}/hell/{other-var}/?do=dnt&y=#xyz';
- $uriObj = new Uri($uri);
+ $uriObj = new RequestUri($uri);
$this->assertEquals('/{some-var}/hell/{other-var}',$uriObj->getPath());
$this->assertTrue($uriObj->hasParameters());
$queryStrVars = $uriObj->getQueryStringVars();
@@ -277,7 +282,7 @@ public function testSplitURI_06() {
*/
public function testSplitURI_07() {
$uri = 'https://www3.programmingacademia.com:80/{some-var}/{x}/{some-var}';
- $uriObj = new Uri($uri);
+ $uriObj = new RequestUri($uri);
$this->assertEquals('/{some-var}/{x}/{some-var}',$uriObj->getPath());
$this->assertEquals(2,count($uriObj->getParameters()));
}
@@ -286,7 +291,7 @@ public function testSplitURI_07() {
*/
public function testSplitURI_08() {
$uri = 'https://programmingacademia.com/Hello World';
- $uriObj = new Uri($uri);
+ $uriObj = new RequestUri($uri);
$this->assertEquals('/Hello World',$uriObj->getPath());
}
/**
@@ -294,7 +299,7 @@ public function testSplitURI_08() {
*/
public function testSplitURI_09() {
$uri = 'https://programmingacademia.com/Hello World? /or Not?super?';
- $uriObj = new Uri($uri);
+ $uriObj = new RequestUri($uri);
$this->assertEquals('/Hello World? /or Not?super?',$uriObj->getPath());
}
/**
@@ -302,7 +307,7 @@ public function testSplitURI_09() {
*/
public function testSplitURI_10() {
$uri = 'https://programmingacademia.com/Hello World? or Not?Yes';
- $uriObj = new Uri($uri);
+ $uriObj = new RequestUri($uri);
$this->assertEquals('/Hello World? or Not',$uriObj->getPath());
}
/**
@@ -310,7 +315,7 @@ public function testSplitURI_10() {
*/
public function testSplitURI_11() {
$uri = 'https://programmingacademia.com/Hello World#or Not#Yes';
- $uriObj = new Uri($uri);
+ $uriObj = new RequestUri($uri);
$this->assertEquals('/Hello World#or Not',$uriObj->getPath());
$this->assertEquals('Yes',$uriObj->getFragment());
}
@@ -319,7 +324,7 @@ public function testSplitURI_11() {
*/
public function testSplitURI_12() {
$uri = 'https://programmingacademia.com/{some-var?}/ok/not/super?one=2';
- $uriObj = new Uri($uri);
+ $uriObj = new RequestUri($uri);
$this->assertEquals('/{some-var?}/ok/not/super',$uriObj->getPath());
$this->assertEquals('one=2',$uriObj->getQueryString());
$this->assertTrue($uriObj->hasParameter('some-var'));
@@ -329,18 +334,19 @@ public function testSplitURI_12() {
*/
public function testSplitURI_13() {
$uri = 'https://programmingacademia.com/{some-var?}/{another?}/not/super';
- $uriObj = new Uri($uri);
+ $uriObj = new RequestUri($uri);
$this->assertEquals('/{some-var?}/{another?}/not/super',$uriObj->getPath());
$this->assertTrue($uriObj->hasParameter('some-var'));
$this->assertTrue($uriObj->hasParameter('another'));
$this->assertTrue($uriObj->isAllParametersSet());
+
}
/**
* @test
*/
public function testSplitURI_14() {
$uri = 'https://programmingacademia.com/{another}/not/{some-var?}/super';
- $uriObj = new Uri($uri);
+ $uriObj = new RequestUri($uri);
$this->assertEquals('/{another}/not/{some-var?}/super',$uriObj->getPath());
$this->assertTrue($uriObj->hasParameter('some-var'));
$this->assertTrue($uriObj->hasParameter('another'));
@@ -353,7 +359,7 @@ public function testSplitURI_15() {
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Empty string not allowed as variable name.');
$uri = 'https://programmingacademia.com/{}/{another}/not/super';
- $uriObj = new Uri($uri);
+ $uriObj = new RequestUri($uri);
}
/**
* @test
@@ -362,6 +368,6 @@ public function testSplitURI_16() {
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Empty string not allowed as variable name.');
$uri = 'https://programmingacademia.com/{?}/{another}/not/super';
- $uriObj = new Uri($uri);
+ $uriObj = new RequestUri($uri);
}
}
diff --git a/tests/WebFiori/Tests/Http/WebServicesManagerTest.php b/tests/WebFiori/Tests/Http/WebServicesManagerTest.php
index 84f2665c..3a819ad0 100644
--- a/tests/WebFiori/Tests/Http/WebServicesManagerTest.php
+++ b/tests/WebFiori/Tests/Http/WebServicesManagerTest.php
@@ -155,7 +155,7 @@ public function testConstructor00() {
$this->clrearVars();
putenv('REQUEST_METHOD=GET');
$api = new SampleServicesManager();
- $this->assertEquals('GET', Request::getMethod());
+ $this->assertEquals('GET', Request::createFromGlobals()->getRequestMethod());
$this->assertNull($api->getCalledServiceName());
$this->assertEquals('1.0.1',$api->getVersion());
$this->assertEquals('NO DESCRIPTION',$api->getDescription());
diff --git a/tests/phpunit10.xml b/tests/phpunit10.xml
index c6ee3335..c63e0e44 100644
--- a/tests/phpunit10.xml
+++ b/tests/phpunit10.xml
@@ -28,6 +28,9 @@
../WebFiori/Http/UriParameter.php
../WebFiori/Http/ObjectMapper.php
../WebFiori/Http/AuthHeader.php
+ ../WebFiori/Http/HttpMessage.php
+ ../WebFiori/Http/RequestV2.php
+ ../WebFiori/Http/RequestUri.php