From 45e64106f20d164a9b2553463a88506f745331d2 Mon Sep 17 00:00:00 2001 From: Wasin Phungwigrai Date: Fri, 20 Feb 2026 15:30:15 +0700 Subject: [PATCH] fix(api): url encode ids in api requests Apply URL encoding to all ID parameters in API endpoint paths to prevent issues with special characters in user IDs, item IDs, and feedback types. This ensures proper handling of strings containing characters that have special meaning in URLs. --- src/Gorse.php | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/Gorse.php b/src/Gorse.php index 851ffa3..e90a3d3 100644 --- a/src/Gorse.php +++ b/src/Gorse.php @@ -38,7 +38,7 @@ function insertUser(User $user): RowAffected */ function getUser(string $user_id): User { - return User::fromJSON($this->request('GET', '/api/user/' . $user_id, null)); + return User::fromJSON($this->request('GET', '/api/user/' . urlencode($user_id), null)); } /** @@ -46,7 +46,7 @@ function getUser(string $user_id): User */ function deleteUser(string $user_id): RowAffected { - return RowAffected::fromJSON($this->request('DELETE', '/api/user/' . $user_id, null)); + return RowAffected::fromJSON($this->request('DELETE', '/api/user/' . urlencode($user_id), null)); } /** @@ -62,7 +62,7 @@ function insertItem(Item $item): RowAffected */ function getItem(string $item_id): Item { - return Item::fromJSON($this->request('GET', '/api/item/' . $item_id, null)); + return Item::fromJSON($this->request('GET', '/api/item/' . urlencode($item_id), null)); } /** @@ -70,7 +70,7 @@ function getItem(string $item_id): Item */ function deleteItem(string $item_id): RowAffected { - return RowAffected::fromJSON($this->request('DELETE', '/api/item/' . $item_id, null)); + return RowAffected::fromJSON($this->request('DELETE', '/api/item/' . urlencode($item_id), null)); } /** @@ -78,7 +78,7 @@ function deleteItem(string $item_id): RowAffected */ function updateItem(string $item_id, Item $item): RowAffected { - return RowAffected::fromJSON($this->request('PATCH', '/api/item/' . $item_id, $item)); + return RowAffected::fromJSON($this->request('PATCH', '/api/item/' . urlencode($item_id), $item)); } /** @@ -94,7 +94,7 @@ function insertFeedback(array $feedback): RowAffected */ function listFeedback(string $feedback_type, string $user_id, string $item_id): array { - return $this->request('GET', '/api/feedback/' . $feedback_type . '/' . $user_id . '/' . $item_id, null); + return $this->request('GET', '/api/feedback/' . urlencode($feedback_type) . '/' . urlencode($user_id) . '/' . urlencode($item_id), null); } /** @@ -102,7 +102,7 @@ function listFeedback(string $feedback_type, string $user_id, string $item_id): */ function getFeedback(string $user_id, string $item_id): array { - return $this->request('GET', '/api/feedback/' . $user_id . '/' . $item_id, null); + return $this->request('GET', '/api/feedback/' . urlencode($user_id) . '/' . urlencode($item_id), null); } /** @@ -110,7 +110,7 @@ function getFeedback(string $user_id, string $item_id): array */ function getFeedbackByType(string $feedback_type): array { - return $this->request('GET', '/api/feedback/' . $feedback_type, null); + return $this->request('GET', '/api/feedback/' . urlencode($feedback_type), null); } /** @@ -118,7 +118,7 @@ function getFeedbackByType(string $feedback_type): array */ function deleteFeedback(string $feedback_type, string $user_id, string $item_id): RowAffected { - return RowAffected::fromJSON($this->request('DELETE', '/api/feedback/' . $feedback_type . '/' . $user_id . '/' . $item_id, null)); + return RowAffected::fromJSON($this->request('DELETE', '/api/feedback/' . urlencode($feedback_type) . '/' . urlencode($user_id) . '/' . urlencode($item_id), null)); } /** @@ -130,7 +130,7 @@ function getRecommend(string $user_id, ?string $write_back_type = null, ?string if ($write_back_type) $params['write-back-type'] = $write_back_type; if ($write_back_delay) $params['write-back-delay'] = $write_back_delay; - return $this->request('GET', '/api/recommend/' . $user_id, null, $params); + return $this->request('GET', '/api/recommend/' . urlencode($user_id), null, $params); } /** @@ -160,7 +160,7 @@ function getNeighbors(string $item_id, int $n = 10, int $offset = 0): array function getItemNeighbors(string $name, string $item_id, int $n = 10, int $offset = 0): array { $scores = []; - $response = $this->request('GET', "/api/item-to-item/$name/$item_id", null, ['n' => $n, 'offset' => $offset]); + $response = $this->request('GET', "/api/item-to-item/" . urlencode($name) . "/" . urlencode($item_id), null, ['n' => $n, 'offset' => $offset]); foreach ($response as $score) { $scores[] = Score::fromJSON($score); } @@ -173,7 +173,7 @@ function getItemNeighbors(string $name, string $item_id, int $n = 10, int $offse function getUserNeighbors(string $name, string $user_id, int $n = 10, int $offset = 0): array { $scores = []; - $response = $this->request('GET', "/api/user-to-user/$name/$user_id", null, ['n' => $n, 'offset' => $offset]); + $response = $this->request('GET', "/api/user-to-user/" . urlencode($name) . "/" . urlencode($user_id), null, ['n' => $n, 'offset' => $offset]); foreach ($response as $score) { $scores[] = Score::fromJSON($score); } @@ -189,7 +189,7 @@ function getNonPersonalized(string $name, ?string $user_id = null, int $n = 10, if ($user_id) $params['user-id'] = $user_id; $scores = []; - $response = $this->request('GET', "/api/non-personalized/$name", null, $params); + $response = $this->request('GET', "/api/non-personalized/" . urlencode($name), null, $params); foreach ($response as $score) { $scores[] = Score::fromJSON($score); }