diff --git a/CHANGELOG.md b/CHANGELOG.md
index 370f08e1..9ad9fc13 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@ and adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
### Added
- [#134](https://github.com/Shopify/shopify-php-api/pull/134) ⚠️ [Breaking] Add support for PHP 8.1 and remove 7.3 from the supported list, since it's no longer supported
+- [#136](https://github.com/Shopify/shopify-php-api/pull/136) Allow full paths in REST requests
### Fixed
diff --git a/docs/usage/rest.md b/docs/usage/rest.md
index 5c4f0e7d..66c3e7b4 100644
--- a/docs/usage/rest.md
+++ b/docs/usage/rest.md
@@ -12,12 +12,12 @@ REST uses `get`, `post`, `put`, and `delete` requests to retrieve, create, updat
| Parameter | Type | Required? | Default Value | Notes |
|:----------|:----------------|:---------:|:----------------:|:-------------------------------------------------|
-| path | string | Yes | | The URL path to request |
-| body | string or array | No | null | Only `Post`, and `put` methods can have body |
+| path | string | Yes | | The requested API endpoint path. This can be one of two formats:
- The path starting after the `/admin/api/{version}/` prefix, such as `'products'`, which executes `/admin/api/{version}/products.json`
- The full path, such as `/admin/oauth/access_scopes.json`
|
+| body | string or array | No | null | Only `post`, and `put` methods can have body |
| headers | array | No | [] | Any extra headers to send along with the request |
| query | array | No | [] | Query parameters as an associative array |
| tries | int | No | null | How many times to attempt the request |
-| dataType | No | No | `DATA_TYPE_JSON` | Only `Post`, and `put` methods can have body |
+| dataType | No | No | `DATA_TYPE_JSON` | Only `post`, and `put` methods can have body |
In the following example we will retrieve a list of products from a shop using `Shopify\Clients\Rest` class.
diff --git a/src/Clients/Http.php b/src/Clients/Http.php
index bba2fbc3..ba235111 100644
--- a/src/Clients/Http.php
+++ b/src/Clients/Http.php
@@ -163,14 +163,10 @@ protected function request(
$client = Context::$HTTP_CLIENT_FACTORY->client();
- if (strpos($path, '/') !== 0) {
- $path = "/$path";
- }
-
$url = (new Uri())
->withScheme('https')
->withHost($this->domain)
- ->withPath($path)
+ ->withPath($this->getRequestPath($path))
->withQuery(http_build_query($query));
$request = new Request($method, $url, $headers);
@@ -217,6 +213,15 @@ protected function request(
return $response;
}
+ protected function getRequestPath(string $path): string
+ {
+ if (strpos($path, '/') !== 0) {
+ $path = "/$path";
+ }
+
+ return $path;
+ }
+
/**
* Logs an API deprecation for the given URL to the app's logged, if one was given.
*
diff --git a/src/Clients/Rest.php b/src/Clients/Rest.php
index 85130266..8f707f0c 100644
--- a/src/Clients/Rest.php
+++ b/src/Clients/Rest.php
@@ -45,7 +45,7 @@ protected function request(
$headers[HttpHeaders::X_SHOPIFY_ACCESS_TOKEN] =
Context::$IS_PRIVATE_APP ? Context::$API_SECRET_KEY : $this->accessToken;
- $response = parent::request($this->getRestPath($path), $method, $body, $headers, $query, $tries, $dataType);
+ $response = parent::request($path, $method, $body, $headers, $query, $tries, $dataType);
return new RestResponse(
$response->getStatusCode(),
@@ -57,10 +57,17 @@ protected function request(
);
}
- private function getRestPath(string $path): string
+ protected function getRequestPath(string $path): string
{
+ $path = parent::getRequestPath($path);
+ $path = preg_replace("/\.json$/", "", $path) . ".json";
+
$apiVersion = Context::$API_VERSION;
- return "admin/api/$apiVersion/$path.json";
+ if (strpos($path, "/admin") !== 0) {
+ $path = "/admin/api/$apiVersion$path";
+ }
+
+ return $path;
}
/**
diff --git a/tests/Clients/RestTest.php b/tests/Clients/RestTest.php
index 659a32f3..600e2e9c 100644
--- a/tests/Clients/RestTest.php
+++ b/tests/Clients/RestTest.php
@@ -84,6 +84,29 @@ public function testCanMakeGetRequest()
$this->assertThat($response, new HttpResponseMatcher(200, [], $this->successResponse));
}
+ public function testAllowsFullPaths()
+ {
+ $headers = ['X-Test-Header' => 'test_value'];
+
+ $client = new Rest($this->domain, 'dummy-token');
+
+ $this->mockTransportRequests([
+ new MockRequest(
+ $this->buildMockHttpResponse(200, $this->successResponse),
+ "https://$this->domain/admin/custom_path.json",
+ 'GET',
+ "Shopify Admin API Library for PHP v$this->version",
+ ['X-Test-Header: test_value', 'X-Shopify-Access-Token: dummy-token'],
+ null,
+ null,
+ false,
+ ),
+ ]);
+
+ $response = $client->get('/admin/custom_path', $headers);
+ $this->assertThat($response, new HttpResponseMatcher(200, [], $this->successResponse));
+ }
+
public function testCanMakeGetRequestWithPathInQuery()
{
$client = new Rest($this->domain, 'dummy-token');