public function testDefaultFormat() { $route = new RestRoute('Api'); $url = new UrlScript(); $url->setPath('/api/foo'); $request = new Request($url); $format = $this->runDetectFormatMethod($route, $request); $this->assertEquals('json', $format); }
/** * @expectedException \Nette\InvalidStateException */ public function testOverrideMethodWithInvalidMethod() { $method = 'invalid'; $route = new RestRoute('Api'); $url = new UrlScript(); $url->setPath('/api/foo'); $url->setQuery(['__method' => $method]); $request = new Request($url, NULL, NULL, NULL, NULL, NULL, 'POST'); $appRequest = $route->match($request); }
/** * Build the URL for given domain alias, path and parameters. * * @param string $name The name of the domain * @param string $path Optional path (without a leading slash) * @param array $params Optional query parameters * * @return Http\UrlScript The URL for the given parameters */ public function createUrl($name, $path = NULL, $params = []) { if (preg_match('~^https?://([^.]+\\.)?twitter\\.com/~', trim($path))) { $url = new Http\UrlScript($path); } else { $url = new Http\UrlScript($this->domains[$name]); $path = $url->getPath() . ltrim($path, '/'); $url->setPath($path); } $url->appendQuery(array_map(function ($param) { return $param instanceof Http\UrlScript ? (string) $param : $param; }, $params)); return $url; }
/** * @dataProvider getActions */ public function testDefault($method, $path, $action, $id = null, $associations = null) { $route = new RestRoute(); $url = new UrlScript(); $url->setPath($path); $request = new Request($url, NULL, NULL, NULL, NULL, NULL, $method); $appRequest = $route->match($request); $this->assertEquals('Foo', $appRequest->getPresenterName()); $this->assertEquals($action, $appRequest->parameters['action']); if ($id) { $this->assertEquals($id, $appRequest->parameters['id']); } if ($associations) { $this->assertSame($associations, $appRequest->parameters['associations']); } }
/** * Creates current HttpRequest object. * @return Request */ public function createHttpRequest() { // DETECTS URI, base path and script path of the request. $url = new UrlScript(); $url->setScheme(!empty($_SERVER['HTTPS']) && strcasecmp($_SERVER['HTTPS'], 'off') ? 'https' : 'http'); $url->setUser(isset($_SERVER['PHP_AUTH_USER']) ? $_SERVER['PHP_AUTH_USER'] : ''); $url->setPassword(isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : ''); // host & port if ((isset($_SERVER[$tmp = 'HTTP_HOST']) || isset($_SERVER[$tmp = 'SERVER_NAME'])) && preg_match('#^([a-z0-9_.-]+|\\[[a-f0-9:]+\\])(:\\d+)?\\z#i', $_SERVER[$tmp], $pair)) { $url->setHost(strtolower($pair[1])); if (isset($pair[2])) { $url->setPort(substr($pair[2], 1)); } elseif (isset($_SERVER['SERVER_PORT'])) { $url->setPort($_SERVER['SERVER_PORT']); } } // path & query if (isset($_SERVER['REQUEST_URI'])) { // Apache, IIS 6.0 $requestUrl = $_SERVER['REQUEST_URI']; } elseif (isset($_SERVER['ORIG_PATH_INFO'])) { // IIS 5.0 (PHP as CGI ?) $requestUrl = $_SERVER['ORIG_PATH_INFO']; if (isset($_SERVER['QUERY_STRING']) && $_SERVER['QUERY_STRING'] != '') { $requestUrl .= '?' . $_SERVER['QUERY_STRING']; } } else { $requestUrl = ''; } $requestUrl = Strings::replace($requestUrl, $this->urlFilters['url']); $tmp = explode('?', $requestUrl, 2); $url->setPath(Strings::replace($tmp[0], $this->urlFilters['path'])); $url->setQuery(isset($tmp[1]) ? $tmp[1] : ''); // normalized url $url->canonicalize(); $url->setPath(Strings::fixEncoding($url->getPath())); // detect script path if (isset($_SERVER['SCRIPT_NAME'])) { $script = $_SERVER['SCRIPT_NAME']; } elseif (isset($_SERVER['DOCUMENT_ROOT'], $_SERVER['SCRIPT_FILENAME']) && strncmp($_SERVER['DOCUMENT_ROOT'], $_SERVER['SCRIPT_FILENAME'], strlen($_SERVER['DOCUMENT_ROOT'])) === 0) { $script = '/' . ltrim(strtr(substr($_SERVER['SCRIPT_FILENAME'], strlen($_SERVER['DOCUMENT_ROOT'])), '\\', '/'), '/'); } else { $script = '/'; } $path = strtolower($url->getPath()) . '/'; $script = strtolower($script) . '/'; $max = min(strlen($path), strlen($script)); for ($i = 0; $i < $max; $i++) { if ($path[$i] !== $script[$i]) { break; } elseif ($path[$i] === '/') { $url->setScriptPath(substr($url->getPath(), 0, $i + 1)); } } // GET, POST, COOKIE $useFilter = !in_array(ini_get('filter.default'), array('', 'unsafe_raw')) || ini_get('filter.default_flags'); parse_str($url->getQuery(), $query); if (!$query) { $query = $useFilter ? filter_input_array(INPUT_GET, FILTER_UNSAFE_RAW) : (empty($_GET) ? array() : $_GET); } $post = $useFilter ? filter_input_array(INPUT_POST, FILTER_UNSAFE_RAW) : (empty($_POST) ? array() : $_POST); $cookies = $useFilter ? filter_input_array(INPUT_COOKIE, FILTER_UNSAFE_RAW) : (empty($_COOKIE) ? array() : $_COOKIE); $gpc = (bool) get_magic_quotes_gpc(); // remove f*****g quotes, control characters and check encoding if ($gpc || !$this->binary) { $list = array(&$query, &$post, &$cookies); while (list($key, $val) = each($list)) { foreach ($val as $k => $v) { unset($list[$key][$k]); if ($gpc) { $k = stripslashes($k); } if (!$this->binary && is_string($k) && (!preg_match(self::CHARS, $k) || preg_last_error())) { // invalid key -> ignore } elseif (is_array($v)) { $list[$key][$k] = $v; $list[] =& $list[$key][$k]; } else { if ($gpc && !$useFilter) { $v = stripSlashes($v); } if (!$this->binary && (!preg_match(self::CHARS, $v) || preg_last_error())) { $v = ''; } $list[$key][$k] = $v; } } } unset($list, $key, $val, $k, $v); } // FILES and create FileUpload objects $files = array(); $list = array(); if (!empty($_FILES)) { foreach ($_FILES as $k => $v) { if (!$this->binary && is_string($k) && (!preg_match(self::CHARS, $k) || preg_last_error())) { continue; } $v['@'] =& $files[$k]; $list[] = $v; } } while (list(, $v) = each($list)) { if (!isset($v['name'])) { continue; } elseif (!is_array($v['name'])) { if ($gpc) { $v['name'] = stripSlashes($v['name']); } if (!$this->binary && (!preg_match(self::CHARS, $v['name']) || preg_last_error())) { $v['name'] = ''; } if ($v['error'] !== UPLOAD_ERR_NO_FILE) { $v['@'] = new FileUpload($v); } continue; } foreach ($v['name'] as $k => $foo) { if (!$this->binary && is_string($k) && (!preg_match(self::CHARS, $k) || preg_last_error())) { continue; } $list[] = array('name' => $v['name'][$k], 'type' => $v['type'][$k], 'size' => $v['size'][$k], 'tmp_name' => $v['tmp_name'][$k], 'error' => $v['error'][$k], '@' => &$v['@'][$k]); } } // HEADERS if (function_exists('apache_request_headers')) { $headers = apache_request_headers(); } else { $headers = array(); foreach ($_SERVER as $k => $v) { if (strncmp($k, 'HTTP_', 5) == 0) { $k = substr($k, 5); } elseif (strncmp($k, 'CONTENT_', 8)) { continue; } $headers[strtr($k, '_', '-')] = $v; } } $remoteAddr = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : NULL; $remoteHost = isset($_SERVER['REMOTE_HOST']) ? $_SERVER['REMOTE_HOST'] : NULL; // proxy foreach ($this->proxies as $proxy) { if (Helpers::ipMatch($remoteAddr, $proxy)) { if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { $remoteAddr = trim(current(explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']))); } if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) { $remoteHost = trim(current(explode(',', $_SERVER['HTTP_X_FORWARDED_HOST']))); } break; } } $method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : NULL; if ($method === 'POST' && isset($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']) && preg_match('#^[A-Z]+\\z#', $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'])) { $method = $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']; } return new Request($url, $query, $post, $files, $cookies, $headers, $method, $remoteAddr, $remoteHost); }
/** * Creates current HttpRequest object. * @return Request */ public function createHttpRequest() { // DETECTS URI, base path and script path of the request. $url = new UrlScript(); $url->setScheme(!empty($_SERVER['HTTPS']) && strcasecmp($_SERVER['HTTPS'], 'off') ? 'https' : 'http'); $url->setUser(isset($_SERVER['PHP_AUTH_USER']) ? $_SERVER['PHP_AUTH_USER'] : ''); $url->setPassword(isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : ''); // host & port if ((isset($_SERVER[$tmp = 'HTTP_HOST']) || isset($_SERVER[$tmp = 'SERVER_NAME'])) && preg_match('#^([a-z0-9_.-]+|\\[[a-f0-9:]+\\])(:\\d+)?\\z#i', $_SERVER[$tmp], $pair)) { $url->setHost(strtolower($pair[1])); if (isset($pair[2])) { $url->setPort(substr($pair[2], 1)); } elseif (isset($_SERVER['SERVER_PORT'])) { $url->setPort($_SERVER['SERVER_PORT']); } } // path & query $requestUrl = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '/'; $requestUrl = Strings::replace($requestUrl, $this->urlFilters['url']); $tmp = explode('?', $requestUrl, 2); $path = Url::unescape($tmp[0], '%/?#'); $path = Strings::fixEncoding(Strings::replace($path, $this->urlFilters['path'])); $url->setPath($path); $url->setQuery(isset($tmp[1]) ? $tmp[1] : ''); // detect script path $lpath = strtolower($path); $script = isset($_SERVER['SCRIPT_NAME']) ? strtolower($_SERVER['SCRIPT_NAME']) : ''; if ($lpath !== $script) { $max = min(strlen($lpath), strlen($script)); for ($i = 0; $i < $max && $lpath[$i] === $script[$i]; $i++) { } $path = $i ? substr($path, 0, strrpos($path, '/', $i - strlen($path) - 1) + 1) : '/'; } $url->setScriptPath($path); // GET, POST, COOKIE $useFilter = !in_array(ini_get('filter.default'), array('', 'unsafe_raw')) || ini_get('filter.default_flags'); $query = $url->getQueryParameters(); $post = $useFilter ? filter_input_array(INPUT_POST, FILTER_UNSAFE_RAW) : (empty($_POST) ? array() : $_POST); $cookies = $useFilter ? filter_input_array(INPUT_COOKIE, FILTER_UNSAFE_RAW) : (empty($_COOKIE) ? array() : $_COOKIE); if (get_magic_quotes_gpc()) { $post = Helpers::stripslashes($post, $useFilter); $cookies = Helpers::stripslashes($cookies, $useFilter); } // remove invalid characters $reChars = '#^[' . self::CHARS . ']*+\\z#u'; if (!$this->binary) { $list = array(&$query, &$post, &$cookies); while (list($key, $val) = each($list)) { foreach ($val as $k => $v) { if (is_string($k) && (!preg_match($reChars, $k) || preg_last_error())) { unset($list[$key][$k]); } elseif (is_array($v)) { $list[$key][$k] = $v; $list[] =& $list[$key][$k]; } else { $list[$key][$k] = (string) preg_replace('#[^' . self::CHARS . ']+#u', '', $v); } } } unset($list, $key, $val, $k, $v); } $url->setQuery($query); // FILES and create FileUpload objects $files = array(); $list = array(); if (!empty($_FILES)) { foreach ($_FILES as $k => $v) { if (!$this->binary && is_string($k) && (!preg_match($reChars, $k) || preg_last_error())) { continue; } $v['@'] =& $files[$k]; $list[] = $v; } } while (list(, $v) = each($list)) { if (!isset($v['name'])) { continue; } elseif (!is_array($v['name'])) { if (get_magic_quotes_gpc()) { $v['name'] = stripSlashes($v['name']); } if (!$this->binary && (!preg_match($reChars, $v['name']) || preg_last_error())) { $v['name'] = ''; } if ($v['error'] !== UPLOAD_ERR_NO_FILE) { $v['@'] = new FileUpload($v); } continue; } foreach ($v['name'] as $k => $foo) { if (!$this->binary && is_string($k) && (!preg_match($reChars, $k) || preg_last_error())) { continue; } $list[] = array('name' => $v['name'][$k], 'type' => $v['type'][$k], 'size' => $v['size'][$k], 'tmp_name' => $v['tmp_name'][$k], 'error' => $v['error'][$k], '@' => &$v['@'][$k]); } } // HEADERS if (function_exists('apache_request_headers')) { $headers = apache_request_headers(); } else { $headers = array(); foreach ($_SERVER as $k => $v) { if (strncmp($k, 'HTTP_', 5) == 0) { $k = substr($k, 5); } elseif (strncmp($k, 'CONTENT_', 8)) { continue; } $headers[strtr($k, '_', '-')] = $v; } } $remoteAddr = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : NULL; $remoteHost = isset($_SERVER['REMOTE_HOST']) ? $_SERVER['REMOTE_HOST'] : NULL; // proxy foreach ($this->proxies as $proxy) { if (Helpers::ipMatch($remoteAddr, $proxy)) { if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { $remoteAddr = trim(current(explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']))); } if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) { $remoteHost = trim(current(explode(',', $_SERVER['HTTP_X_FORWARDED_HOST']))); } break; } } $method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : NULL; if ($method === 'POST' && isset($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']) && preg_match('#^[A-Z]+\\z#', $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'])) { $method = $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']; } // raw body $rawBodyCallback = function () { static $rawBody; if (PHP_VERSION_ID >= 50600) { return file_get_contents('php://input'); } elseif ($rawBody === NULL) { // can be read only once in PHP < 5.6 $rawBody = (string) file_get_contents('php://input'); } return $rawBody; }; return new Request($url, NULL, $post, $files, $cookies, $headers, $method, $remoteAddr, $remoteHost, $rawBodyCallback); }
/** * Creates current HttpRequest object. * @return Request */ public function createHttpRequest() { // DETECTS URI, base path and script path of the request. $url = new UrlScript(); $url->setScheme(!empty($_SERVER['HTTPS']) && strcasecmp($_SERVER['HTTPS'], 'off') ? 'https' : 'http'); $url->setUser(isset($_SERVER['PHP_AUTH_USER']) ? $_SERVER['PHP_AUTH_USER'] : ''); $url->setPassword(isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : ''); // host & port if ((isset($_SERVER[$tmp = 'HTTP_HOST']) || isset($_SERVER[$tmp = 'SERVER_NAME'])) && preg_match('#^([a-z0-9_.-]+|\\[[a-f0-9:]+\\])(:\\d+)?\\z#i', $_SERVER[$tmp], $pair)) { $url->setHost(strtolower($pair[1])); if (isset($pair[2])) { $url->setPort((int) substr($pair[2], 1)); } elseif (isset($_SERVER['SERVER_PORT'])) { $url->setPort((int) $_SERVER['SERVER_PORT']); } } // path & query $requestUrl = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '/'; $requestUrl = preg_replace('#^\\w++://[^/]++#', '', $requestUrl); $requestUrl = Strings::replace($requestUrl, $this->urlFilters['url']); $tmp = explode('?', $requestUrl, 2); $path = Url::unescape($tmp[0], '%/?#'); $path = Strings::fixEncoding(Strings::replace($path, $this->urlFilters['path'])); $url->setPath($path); $url->setQuery(isset($tmp[1]) ? $tmp[1] : ''); // detect script path $lpath = strtolower($path); $script = isset($_SERVER['SCRIPT_NAME']) ? strtolower($_SERVER['SCRIPT_NAME']) : ''; if ($lpath !== $script) { $max = min(strlen($lpath), strlen($script)); for ($i = 0; $i < $max && $lpath[$i] === $script[$i]; $i++) { } $path = $i ? substr($path, 0, strrpos($path, '/', $i - strlen($path) - 1) + 1) : '/'; } $url->setScriptPath($path); // GET, POST, COOKIE $useFilter = !in_array(ini_get('filter.default'), ['', 'unsafe_raw']) || ini_get('filter.default_flags'); $query = $url->getQueryParameters(); $post = $useFilter ? filter_input_array(INPUT_POST, FILTER_UNSAFE_RAW) : (empty($_POST) ? [] : $_POST); $cookies = $useFilter ? filter_input_array(INPUT_COOKIE, FILTER_UNSAFE_RAW) : (empty($_COOKIE) ? [] : $_COOKIE); // remove invalid characters $reChars = '#^[' . self::CHARS . ']*+\\z#u'; if (!$this->binary) { $list = [&$query, &$post, &$cookies]; while (list($key, $val) = each($list)) { foreach ($val as $k => $v) { if (is_string($k) && (!preg_match($reChars, $k) || preg_last_error())) { unset($list[$key][$k]); } elseif (is_array($v)) { $list[$key][$k] = $v; $list[] =& $list[$key][$k]; } else { $list[$key][$k] = (string) preg_replace('#[^' . self::CHARS . ']+#u', '', $v); } } } unset($list, $key, $val, $k, $v); } $url->setQuery($query); // FILES and create FileUpload objects $files = []; $list = []; if (!empty($_FILES)) { foreach ($_FILES as $k => $v) { if (!$this->binary && is_string($k) && (!preg_match($reChars, $k) || preg_last_error())) { continue; } $v['@'] =& $files[$k]; $list[] = $v; } } while (list(, $v) = each($list)) { if (!isset($v['name'])) { continue; } elseif (!is_array($v['name'])) { if (!$this->binary && (!preg_match($reChars, $v['name']) || preg_last_error())) { $v['name'] = ''; } if ($v['error'] !== UPLOAD_ERR_NO_FILE) { $v['@'] = new FileUpload($v); } continue; } foreach ($v['name'] as $k => $foo) { if (!$this->binary && is_string($k) && (!preg_match($reChars, $k) || preg_last_error())) { continue; } $list[] = ['name' => $v['name'][$k], 'type' => $v['type'][$k], 'size' => $v['size'][$k], 'tmp_name' => $v['tmp_name'][$k], 'error' => $v['error'][$k], '@' => &$v['@'][$k]]; } } // HEADERS if (function_exists('apache_request_headers')) { $headers = apache_request_headers(); } else { $headers = []; foreach ($_SERVER as $k => $v) { if (strncmp($k, 'HTTP_', 5) == 0) { $k = substr($k, 5); } elseif (strncmp($k, 'CONTENT_', 8)) { continue; } $headers[strtr($k, '_', '-')] = $v; } } $remoteAddr = !empty($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : NULL; $remoteHost = !empty($_SERVER['REMOTE_HOST']) ? $_SERVER['REMOTE_HOST'] : NULL; // use real client address and host if trusted proxy is used $usingTrustedProxy = $remoteAddr && array_filter($this->proxies, function ($proxy) use($remoteAddr) { return Helpers::ipMatch($remoteAddr, $proxy); }); if ($usingTrustedProxy) { if (!empty($_SERVER['HTTP_FORWARDED'])) { $forwardParams = preg_split('/[,;]/', $_SERVER['HTTP_FORWARDED']); foreach ($forwardParams as $forwardParam) { list($key, $value) = explode('=', $forwardParam, 2) + [1 => NULL]; $proxyParams[strtolower(trim($key))][] = trim($value, " \t\""); } if (isset($proxyParams['for'])) { $address = $proxyParams['for'][0]; if (strpos($address, '[') === FALSE) { //IPv4 $remoteAddr = explode(':', $address)[0]; } else { //IPv6 $remoteAddr = substr($address, 1, strpos($address, ']') - 1); } } if (isset($proxyParams['host']) && count($proxyParams['host']) === 1) { $host = $proxyParams['host'][0]; $startingDelimiterPosition = strpos($host, '['); if ($startingDelimiterPosition === FALSE) { //IPv4 $remoteHostArr = explode(':', $host); $remoteHost = $remoteHostArr[0]; if (isset($remoteHostArr[1])) { $url->setPort((int) $remoteHostArr[1]); } } else { //IPv6 $endingDelimiterPosition = strpos($host, ']'); $remoteHost = substr($host, strpos($host, '[') + 1, $endingDelimiterPosition - 1); $remoteHostArr = explode(':', substr($host, $endingDelimiterPosition)); if (isset($remoteHostArr[1])) { $url->setPort((int) $remoteHostArr[1]); } } } $scheme = isset($proxyParams['scheme']) && count($proxyParams['scheme']) === 1 ? $proxyParams['scheme'][0] : 'http'; $url->setScheme(strcasecmp($scheme, 'https') === 0 ? 'https' : 'http'); } else { if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO'])) { $url->setScheme(strcasecmp($_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') === 0 ? 'https' : 'http'); } if (!empty($_SERVER['HTTP_X_FORWARDED_PORT'])) { $url->setPort((int) $_SERVER['HTTP_X_FORWARDED_PORT']); } if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { $xForwardedForWithoutProxies = array_filter(explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']), function ($ip) { return !array_filter($this->proxies, function ($proxy) use($ip) { return Helpers::ipMatch(trim($ip), $proxy); }); }); $remoteAddr = trim(end($xForwardedForWithoutProxies)); $xForwardedForRealIpKey = key($xForwardedForWithoutProxies); } if (isset($xForwardedForRealIpKey) && !empty($_SERVER['HTTP_X_FORWARDED_HOST'])) { $xForwardedHost = explode(',', $_SERVER['HTTP_X_FORWARDED_HOST']); if (isset($xForwardedHost[$xForwardedForRealIpKey])) { $remoteHost = trim($xForwardedHost[$xForwardedForRealIpKey]); } } } } // method, eg. GET, PUT, ... $method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : NULL; if ($method === 'POST' && isset($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']) && preg_match('#^[A-Z]+\\z#', $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'])) { $method = $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']; } // raw body $rawBodyCallback = function () { return file_get_contents('php://input'); }; return new Request($url, NULL, $post, $files, $cookies, $headers, $method, $remoteAddr, $remoteHost, $rawBodyCallback); }
/** * @dataProvider getVersions */ public function testModuleVersioning($module, $path, $expectedPresenterName, $expectedUrl) { $route = new RestRoute($module); $route->useURLModuleVersioning(RestRoute::MODULE_VERSION_PATH_PREFIX_PATTERN, [NULL => 'V1', 'v1' => 'V1', 'v2' => 'V2']); $url = new UrlScript(); $url->setPath($path); $request = new Request($url, NULL, NULL, NULL, NULL, NULL, 'GET'); $appRequest = $route->match($request); $this->assertEquals($expectedPresenterName, $appRequest->getPresenterName()); $refUrl = new Url('http://localhost'); $url = $route->constructUrl($appRequest, $refUrl); $this->assertEquals($expectedUrl, $url); }