diff --git a/flight/net/Route.php b/flight/net/Route.php
index b3758c3..4ff28d7 100644
--- a/flight/net/Route.php
+++ b/flight/net/Route.php
@@ -178,11 +178,16 @@ final class Route
 	 * @return string
 	 */
 	public function hydrateUrl(array $params = []): string {
-		$url = preg_replace_callback("/(?:@([a-zA-Z]+)(?:\:([^\/]+))?)?/i", function($match) use ($params) {
+		$url = preg_replace_callback("/(?:@([a-zA-Z]+)(?:\:([^\/]+))?\)*)/i", function($match) use ($params) {
 			if(isset($match[1]) && isset($params[$match[1]])) {
 				return $params[$match[1]];
 			}
 		}, $this->pattern);
+
+		// catches potential optional parameter
+		$url = str_replace('(/', '/', $url);
+		// trim any trailing slashes
+		$url = rtrim($url, '/');
 		return $url;
 	}
 }
diff --git a/tests/RouterTest.php b/tests/RouterTest.php
index a970990..821d358 100644
--- a/tests/RouterTest.php
+++ b/tests/RouterTest.php
@@ -500,6 +500,18 @@ class RouterTest extends PHPUnit\Framework\TestCase
 		$this->assertEquals('/path1/123', $url);
 	}
 
+	public function testGetUrlByAliasSimpleOptionalParamsWithParam() {
+		$this->router->map('/path1(/@id)', [$this, 'ok'], false, 'path1');
+		$url = $this->router->getUrlByAlias('path1', ['id' => 123]);
+		$this->assertEquals('/path1/123', $url);
+	}
+
+	public function testGetUrlByAliasSimpleOptionalParamsNoParam() {
+		$this->router->map('/path1(/@id)', [$this, 'ok'], false, 'path1');
+		$url = $this->router->getUrlByAlias('path1');
+		$this->assertEquals('/path1', $url);
+	}
+
 	public function testGetUrlByAliasMultipleParams() {
 		$this->router->map('/path1/@id/@name', [$this, 'ok'], false, 'path1');
 		$url = $this->router->getUrlByAlias('path1', ['id' => 123, 'name' => 'abc']);
@@ -511,4 +523,22 @@ class RouterTest extends PHPUnit\Framework\TestCase
 		$url = $this->router->getUrlByAlias('path1', ['id' => '123', 'name' => 'abc']);
 		$this->assertEquals('/path1/123/abc', $url);
 	}
+
+	public function testGetUrlByAliasMultipleComplexOptionalParamsMissingOne() {
+		$this->router->map('/path1(/@id:[0-9]+(/@name(/@crazy:[a-z]{5})))', [$this, 'ok'], false, 'path1');
+		$url = $this->router->getUrlByAlias('path1', ['id' => '123', 'name' => 'abc']);
+		$this->assertEquals('/path1/123/abc', $url);
+	}
+
+	public function testGetUrlByAliasMultipleComplexOptionalParamsAllParams() {
+		$this->router->map('/path1(/@id:[0-9]+(/@name(/@crazy:[a-z]{5})))', [$this, 'ok'], false, 'path1');
+		$url = $this->router->getUrlByAlias('path1', ['id' => '123', 'name' => 'abc', 'crazy' => 'xyz']);
+		$this->assertEquals('/path1/123/abc/xyz', $url);
+	}
+
+	public function testGetUrlByAliasMultipleComplexOptionalParamsNoParams() {
+		$this->router->map('/path1(/@id:[0-9]+(/@name(/@crazy:[a-z]{5})))', [$this, 'ok'], false, 'path1');
+		$url = $this->router->getUrlByAlias('path1');
+		$this->assertEquals('/path1', $url);
+	}
 }