diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d39c985..18397f7 100755 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,11 +11,11 @@ jobs: if: "!contains(github.event.head_commit.message, 'skip ci')" name: PHP ${{ matrix.php-versions }} on ${{ matrix.os }} runs-on: ${{ matrix.os }} - continue-on-error: ${{ matrix.php-versions >= '8.5' }} + continue-on-error: ${{ matrix.php-versions >= '8.6' }} strategy: fail-fast: false matrix: - php-versions: ['7.4', '8.0', '8.1', '8.2', '8.3', '8.4', '8.5'] + php-versions: ['7.4', '8.0', '8.1', '8.2', '8.3', '8.4', '8.5', '8.6'] os: [ubuntu-latest, windows-latest] steps: @@ -48,7 +48,7 @@ jobs: - name: Install dependencies run: > - curl -sSL https://baltocdn.com/xp-framework/xp-runners/distribution/downloads/e/entrypoint/xp-run-8.8.0.sh > xp-run && + curl -sSL https://github.com/xp-runners/reference/releases/download/v9.2.0/xp-run-9.2.0.sh > xp-run && composer install --prefer-dist && echo "vendor/autoload.php" > composer.pth diff --git a/src/main/php/webservices/rest/Endpoint.class.php b/src/main/php/webservices/rest/Endpoint.class.php index ed17d54..a5379e3 100755 --- a/src/main/php/webservices/rest/Endpoint.class.php +++ b/src/main/php/webservices/rest/Endpoint.class.php @@ -57,12 +57,7 @@ public function __construct($base, $formats= null, $compressing= null) { } else if ($user) { $this->headers['Authorization']= 'Bearer '.$user; } - - $this->base= $uri->using() - ->authority(new Authority($authority->host(), $authority->port())) - ->path(rtrim($uri->path() ?? '', '/').'/') - ->create() - ; + $this->base= $uri->authenticated(null); $this->formats= $formats ?: Formats::defaults(); $this->transfer= new Streamed($this); @@ -159,7 +154,7 @@ public function with($arg, $value= null) { * @param [:string] $segments * @return webservices.rest.RestResource */ - public function resource($path, $segments= []) { + public function resource($path= '', $segments= []) { return new RestResource($this, $path, $segments); } @@ -186,7 +181,8 @@ public function setTrace($cat) { * @return webservices.rest.io.Transmission */ public function open(RestRequest $request) { - $target= $this->base->resolve($request->path()); + $path= $request->path(); + $target= '' === $path ? $this->base : $this->base->resolve($request->path()); $conn= $this->connections->__invoke($target); // Use request timeouts if supplied, otherwise use those of the connection diff --git a/src/main/php/webservices/rest/RestResource.class.php b/src/main/php/webservices/rest/RestResource.class.php index fb526f9..69ab9e4 100755 --- a/src/main/php/webservices/rest/RestResource.class.php +++ b/src/main/php/webservices/rest/RestResource.class.php @@ -21,7 +21,7 @@ class RestResource { * @param string $path * @param [:string] $segments */ - public function __construct(Endpoint $endpoint, $path, $segments= []) { + public function __construct(Endpoint $endpoint, $path= '', $segments= []) { $this->endpoint= $endpoint; $this->target= $this->resolve($path, $segments, true); } @@ -60,7 +60,7 @@ private function resolve($resource, $segments, $encode) { /** Returns target URI */ public function uri(): URI { - return $this->endpoint->base()->resolve($this->target); + return '' === $this->target ? $this->endpoint->base() : $this->endpoint->base()->resolve($this->target); } /** diff --git a/src/main/php/webservices/rest/TestEndpoint.class.php b/src/main/php/webservices/rest/TestEndpoint.class.php index 210ecfa..83b12e9 100644 --- a/src/main/php/webservices/rest/TestEndpoint.class.php +++ b/src/main/php/webservices/rest/TestEndpoint.class.php @@ -50,7 +50,8 @@ public function __construct(array $routes, $base= '/') { private function handle($call) { $request= $call->request(); - $match= $request->method().' '.$this->base->resolve($request->path())->path(); + $path= $request->path(); + $match= $request->method().' '.('' === $path ? $this->base->path() : $this->base->resolve($path)->path()); foreach ($this->routes as $pattern => $handler) { if (preg_match($pattern, $match, $capture)) return $handler($call, $capture); } diff --git a/src/test/php/webservices/rest/unittest/RestResourceTest.class.php b/src/test/php/webservices/rest/unittest/RestResourceTest.class.php index eebbc26..dff85f3 100755 --- a/src/test/php/webservices/rest/unittest/RestResourceTest.class.php +++ b/src/test/php/webservices/rest/unittest/RestResourceTest.class.php @@ -8,8 +8,8 @@ class RestResourceTest { /** @return webservices.rest.Endpoint */ - private function endpoint() { - return new class('https://api.example.com/') extends Endpoint { + private function endpoint($base= 'https://api.example.com/') { + return new class($base) extends Endpoint { public $sent= []; public function execute(RestRequest $request) { $this->sent[]= $request; @@ -54,6 +54,14 @@ public function uri() { ); } + #[Test, Values(['https://api.example.com/', 'https://api.example.com/services/mcp', 'https://api.example.com/services/mcp/'])] + public function base_resource($base) { + Assert::equals( + new URI($base), + (new RestResource($this->endpoint($base)))->uri() + ); + } + #[Test] public function uri_with_segments() { Assert::equals( diff --git a/src/test/php/webservices/rest/unittest/TestEndpointTest.class.php b/src/test/php/webservices/rest/unittest/TestEndpointTest.class.php index 77d6787..be5c047 100755 --- a/src/test/php/webservices/rest/unittest/TestEndpointTest.class.php +++ b/src/test/php/webservices/rest/unittest/TestEndpointTest.class.php @@ -30,7 +30,7 @@ public function routed_path_under_base($resource) { '/api/users/self' => function($call) { return $call->respond(307, 'Temporary Redirect', ['Location' => '/api/users/6100']); } - ], '/api'); + ], '/api/'); $r= $fixture->resource($resource)->get(); Assert::equals(307, $r->status());