Creating Better REST URL’s for Javascript clients

Sumanth
3 min readApr 2, 2017

--

If you have gone through the initial hero application of Angular 2 and have started to dive deep into Angular applications especially integrating Angular 2 with backed, one question always comes to your mind — Maintainability. As your application code grows, you might start to have a lot of rest url’s which you would have to integrate with your Angular 2 App. How to maintain so many rest-urls, their parameters, query parameters etc. This scalability/ maintainability produces a spaghetti code with url’s being spread across multiple services or url’s which are populated based on if else or for..in conditions and finally end up looking really ugly.

Let me start with some examples which I have come across and might give you an idea at what I might be saying

Example 1: Building the URL within the service

getOrganization(organizatinId: number) {
....
....
this.restClient.get('/organizations/'+organizationId+'profile').subscribe();
....
....
}
uploadFile(organizatinId: number, type: string, title: string, data: any) {
this._restclient.post('/organizations/'+organizationId+'/profile/upload?type=' + type + '&title=' + title, data).subscribe();
}

We all know that these url’s simply don’t work in the long run. Since the same part is replicated across multiple services/methods (post/put etc.).

Example 2: Building the URL using template strings and template expression

getOrganization(organizationId: number) {
....
....
let url = apiEndpoint+`/organizations/${organizationId}/profile`;
this.restClient.get(url).subscribe();}

This is better because we can interpolate the url’s now and maintain it at one place. This can be extracted to class variable and maintained at that place

export class OrganizationAPIs {readonly  organizationProfileURL = apiEndpoint+`/organizations/${organizationId}/profile`;
}

The only downside with these url’s are that all the placeholders needs to be replaced. Imagine an url with query string parameters where you might not use all the query string parameters.

let url =  apiEndpoint+`/organizations/${organizationId}/profile/upload?type=${mediaTypeName}&title=${titleName}`;

In the above example what if I don’t want to use mediaTypeName query string parameter at all. With these url’s its not possible to skip placeholders.

So My Idea was to extend the concept of namedParameters to build rest urls. Angular 2 already does it for the browser urls, hero/:heroId . Based on this I created a simple npm module, rest-url-builder, which does the same.

As usual let’s begin with an example,

import { RestURLBuilder } from 'rest-url-builder';const urlBuilder = new RestURLBuilder();private  organizationProfileURL = apiEndpoint+'/organizations/:organizationId/profile';private uploadFileURL = this.organizationProfileURL+'/upload?type=:typeName&title=:titleName';getOrganization(organizationId: number) {let urlBuilder = this.urlBuilder.buildRestURL(this.organizationProfileURL);
urlBuilder.setNamedParameter('organizationId', organizationId);
// finalURL = https://fromsomewhere.com/organizations/4
let finalURL = urlBuilder.get();
}
uploadFile(organizatinId: number, mediaType: string, title: string, data: any) {let urlBuilder = this.urlBuilder.buildRestURL(this.uploadFileURL);
urlBuilder.setNamedParameter('organizationId', organizationId);
urlBuilder.setQueryParameter('title', title);
// since we are not going to set mediaType parameter it will be a part of // the finalURL
// finalURL = https://fromsomewhere.com/organizations/4?
//title=NewFile
let finalURL = urlBuilder.get();
}

In general there are four main methods in this module,

let urlBuilder = urlBuilder.buildRestURL(urlWithNamedParameters);
urlBuilder.setNamedParameter('namedParameter1', ''+Parametervalue);
urlBuilder.setQueryParameter('queryParameter1', ''+queryParamValue);
urlBuilder.get();

Now all the service methods just contain the above four lines/more depending on number of parameters. And all the url’s for a particular rest api can be maintained at one place.

For more examples please check my repository rest-url-builder. In another post I will be showing how backend url’s are refactored in one of the Angular 2 projects I am working on.

--

--