From d13b4cdc022b43fc244e401128fef988b1661cb4 Mon Sep 17 00:00:00 2001 From: Andrei Kakhanouski Date: Wed, 16 Jul 2025 11:22:09 +0200 Subject: [PATCH] bugfix/URI-Parameter-Syntax-Update-Migrating-from-Colon-to-Curly-Brackets --- API_Reference.md | 2 +- Developer_Guide.md | 14 +++++++------- .../default/classes/CustomerWebServiceDemo.cls | 2 +- .../main/default/classes/libak_RestProcessor.cls | 8 ++++---- .../main/default/classes/libak_RestRouter.cls | 4 ++-- .../classes/tests/libak_TestRestFramework.cls | 2 +- .../classes/tests/libak_TestRestProcessor.cls | 2 +- .../default/classes/tests/libak_TestRestRouter.cls | 2 +- 8 files changed, 18 insertions(+), 18 deletions(-) diff --git a/API_Reference.md b/API_Reference.md index 38beb9e..894e338 100644 --- a/API_Reference.md +++ b/API_Reference.md @@ -183,7 +183,7 @@ This method is the entry point for processing incoming REST requests. It dynamic Sets the URI template for this `libak_RestProcessor`. The URI template defines the expected structure of the incoming URI, including any URI parameters. - Parameters: - - `uriTemplate` (String): The URI template to set, in the format "/service/resource/:paramName". The colon (:) is used to denote URI parameters, and the parameter name is used as the key for mapping URI values. + - `uriTemplate` (String): The URI template to set, in the format "/service/resource/:paramName". The {paramName} (string inside curly brackets) is used to denote URI parameters, and the parameter name is used as the key for mapping URI values. - Returns: The current `libak_RestProcessor` instance with the URI template set. #### `useRestRequest(RestRequest request)` diff --git a/Developer_Guide.md b/Developer_Guide.md index 78cf782..3874a54 100644 --- a/Developer_Guide.md +++ b/Developer_Guide.md @@ -80,7 +80,7 @@ Now is time to thing about routing. Analyzing our requirements we can define two routes: - **`v1/customers`**: the route will be used to retrieve list of our customers and create new. -- **`v1/customers/:customer_id`**: the route will be used for manipulations on the dedicated customer. Here you can see the colon character `:` before the `customer_id`. This way we mark a named URI params that we can easily get access to in the Rest Processor (look at Step 4 for details). +- **`v1/customers/{customer_id}`**: the route will be used for manipulations on the dedicated customer. Here you can see the `customer_id` wrapped in `{}` curly brackets. This way we mark a named URI params that we can easily get access to in the Rest Processor (look at Step 4 for details). To create a RestRouter we have to extend the `libak_RestRouter` class and override the `setRoutes()` method where we have to specify which Rest Processor we handle which route by setting the `routeToRestProcessorType` protected property as `:`. @@ -91,7 +91,7 @@ public class CustomerRestRouter extends libak_RestRouter { override public libak_RestRouter setRoutes() { this.routeToRestProcessorType = new Map{ '/v1/customers' => CustomersProcessorV1.class, - '/v1/customers/:customer_sf_id' => CustomerProcessorV1.class + '/v1/customers/{customer_sf_id}' => CustomerProcessorV1.class }; return this; } @@ -107,7 +107,7 @@ public class CustomerRestRouter extends libak_RestRouter { override public libak_RestRouter setRoutes() { this.routeToRestProcessorType = new Map{ '/v1/customers' => CustomersProcessorV1.class, - '/v1/customers/:customer_sf_id' => CustomersProcessorV1.class + '/v1/customers/{customer_sf_id}' => CustomersProcessorV1.class }; return this; } @@ -142,7 +142,7 @@ global with sharing class CustomerWebServiceDemo { override public libak_RestRouter setRoutes() { this.routeToRestProcessorType = new Map{ '/v1/customers' => CustomersProcessorV1.class, - '/v1/customers/:customer_sf_id' => CustomerProcessorV1.class + '/v1/customers/{customer_sf_id}' => CustomerProcessorV1.class }; return this; } @@ -158,7 +158,7 @@ Now it's time to implement our REST Processors. As you remember we agreed to have two of them: - `CustomersProcessorV1` for `/v1/customers` -- `CustomerProcessorV1` for `/v1/customers/:customer_sf_id` +- `CustomerProcessorV1` for `/v1/customers/{customer_sf_id}` Here is a few things you have to consider about it: - Our rest processors have to `extend` the `libak_RestProcessor` @@ -171,7 +171,7 @@ Here is a few things you have to consider about it: All these methods have to return the `libak_IRestResponse`. - the `libak_RestProcessor` provides set of methods to easily get access to URI params, query params, and headers: - - `getUriParam(String paramName)` - remember about the colon character `:` we saw in the routes? It allows us to use those "variable" names to take the proper URI param like this: `this.getUriParam('customer_sf_id')` + - `getUriParam(String paramName)` - remember about the curly brackets characters `{paramName}` we saw in the routes? It allows us to use those "variable" names to take the proper URI param like this: `this.getUriParam('customer_sf_id')` - `getQueryParam(String paramName)` - `getHeader(String headerName)` @@ -288,7 +288,7 @@ global with sharing class CustomerWebServiceDemo { override public libak_RestRouter setRoutes() { this.routeToRestProcessorType = new Map{ '/v1/customers' => CustomersProcessorV1.class, - '/v1/customers/:customer_sf_id' => CustomerProcessorV1.class + '/v1/customers/{customer_sf_id}' => CustomerProcessorV1.class }; return this; } diff --git a/demo-app/main/default/classes/CustomerWebServiceDemo.cls b/demo-app/main/default/classes/CustomerWebServiceDemo.cls index 1af9063..dacc432 100644 --- a/demo-app/main/default/classes/CustomerWebServiceDemo.cls +++ b/demo-app/main/default/classes/CustomerWebServiceDemo.cls @@ -21,7 +21,7 @@ global with sharing class CustomerWebServiceDemo { override public libak_RestRouter setRoutes() { this.routeToRestProcessorType = new Map{ '/v1/customers' => CustomersProcessorV1.class, - '/v1/customers/:customer_sf_id' => CustomerProcessorV1.class + '/v1/customers/{customer_sf_id}' => CustomerProcessorV1.class }; return this; } diff --git a/force-app/main/default/classes/libak_RestProcessor.cls b/force-app/main/default/classes/libak_RestProcessor.cls index dc94f4e..fe10dce 100644 --- a/force-app/main/default/classes/libak_RestProcessor.cls +++ b/force-app/main/default/classes/libak_RestProcessor.cls @@ -57,8 +57,8 @@ public virtual class libak_RestProcessor { * Sets the URI template for this `libak_RestProcessor`. The URI template defines the expected structure * of the incoming URI, including any URI parameters. * - * @param uriTemplate The URI template to set, in the format "/service/resource/:paramName". - * The colon (:) is used to denote URI parameters, and the parameter name is + * @param uriTemplate The URI template to set, in the format "/service/resource/{paramName}". + * The {paramName} (string inside curly brackets) is used to denote URI parameters, and the parameter name is * used as the key for mapping URI values. * @return The current `libak_RestProcessor` instance with the URI template set. */ @@ -231,8 +231,8 @@ public virtual class libak_RestProcessor { while (!templateItems.isEmpty()) { String templateItem = templateItems.remove(0); String uriItem = uriItems.remove(0); - if (templateItem.startsWith(':')) { - this.uriParamsMap.put(templateItem.substringAfter(':'), uriItem); + if (templateItem.startsWith('{')) { + this.uriParamsMap.put(templateItem.substringAfter('{').subStringBefore('}'), uriItem); } } } diff --git a/force-app/main/default/classes/libak_RestRouter.cls b/force-app/main/default/classes/libak_RestRouter.cls index a2821c6..f7a16dd 100644 --- a/force-app/main/default/classes/libak_RestRouter.cls +++ b/force-app/main/default/classes/libak_RestRouter.cls @@ -87,8 +87,8 @@ public abstract class libak_RestRouter { private Boolean isRouteExists(String route, String requestURI) { String routeTemplateRegEx = route .replaceAll('\\*', '\\.+') - .replaceAll('\\:(.+?)/', '\\.+/') - .replaceAll('\\:(.+?)$', '\\.+'); + .replaceAll('\\{(.+?)/', '\\.+/') + .replaceAll('\\{(.+?)$', '\\.+'); return Pattern.matches('(?i)' + routeTemplateRegEx, requestURI.replaceAll('(\\/+)$', '')); } } \ No newline at end of file diff --git a/force-app/main/default/classes/tests/libak_TestRestFramework.cls b/force-app/main/default/classes/tests/libak_TestRestFramework.cls index ce49c79..fc2a40d 100644 --- a/force-app/main/default/classes/tests/libak_TestRestFramework.cls +++ b/force-app/main/default/classes/tests/libak_TestRestFramework.cls @@ -1,7 +1,7 @@ @IsTest public with sharing class libak_TestRestFramework { - public static final String URI_TEMPLATE_WITH_PARAMS = '/testRestFramework/:uriParam'; + public static final String URI_TEMPLATE_WITH_PARAMS = '/testRestFramework/{uriParam}'; public static final String URI_TEMPLATE_WITHOUT_PARAMS = '/testRestFramework'; @IsTest diff --git a/force-app/main/default/classes/tests/libak_TestRestProcessor.cls b/force-app/main/default/classes/tests/libak_TestRestProcessor.cls index 49e0206..65d21e2 100644 --- a/force-app/main/default/classes/tests/libak_TestRestProcessor.cls +++ b/force-app/main/default/classes/tests/libak_TestRestProcessor.cls @@ -96,7 +96,7 @@ public with sharing class libak_TestRestProcessor { private static libak_RestProcessor prepareDefaultRestProcessor(RestRequest request) { return new libak_RestProcessor() .useRestRequest(request) - .useUriTemplate('/testRestRouter/:uriParam') + .useUriTemplate('/testRestRouter/{uriParam}') .useRestLogger(null) .useErrorResponseFactory(new libak_ErrorResponseFactory()); } diff --git a/force-app/main/default/classes/tests/libak_TestRestRouter.cls b/force-app/main/default/classes/tests/libak_TestRestRouter.cls index 151fee0..d3dc6cd 100644 --- a/force-app/main/default/classes/tests/libak_TestRestRouter.cls +++ b/force-app/main/default/classes/tests/libak_TestRestRouter.cls @@ -1,7 +1,7 @@ @IsTest public with sharing class libak_TestRestRouter { - public static final String URI_TEMPLATE = '/testRestRouter/:uriParam'; + public static final String URI_TEMPLATE = '/testRestRouter/{uriParam}'; @IsTest static void testNewRestProcessorWithCustomLoggerAndErrorResponseFactory(){