Implementing REST Services For Mobile

http://justmobiledev.com/wp-content/uploads/2019/01/rest_services_for_mobile.jpgImplementing REST Services For Mobile

This post reviews some server-side and client-side best practices for implementing REST Services for mobile.












Server-Side Best Practices

Follow REST protocol

I’m often surprised to see that developers implement “REST” and don’t follow the protocol. There are two important elements of REST:

1. The way to access the data is via URI’s that reference the target entity. So name the access method according to the entity, not an action.

For example, if you want to query users, your uri should be something like http://<your domain>/user, not something like http://<your domain>/getUsers.

2. The second protocol convention is to use HTTP methods to identify the action you want to perform on the data, e.g. POST to create, GET to retrieve, PUT to update, DELETE to delete.

More about REST protocol here.

Implement a predominant Authentication method

Your web services should be authenticated. Otherwise you are running the risk of your services getting exploited in a heartbeat. A word of caution: if you stand up a new VM, expect about 250,000 attempts to break into your VM within a month.

When evaluating Authentication methods, I would advise against trying to reinvent the wheel. If you’ve ever read an RFC, you probably know that there are an awful lot of smart people sitting at IETF, so unless you have a really good reason, I wouldn’t come up with my own authentication protocol.

I suggest to take a look at oAuth, a fairly mature authentication protocol that’s been around since 2006 and has been implemented by all of the big players: Google, Amazon, Facebook and Twitter.

Instead of implementing the authentication protocol from scratch, I would take a look at what libraries are already available that implement it. For example, oAuth has been implemented in most languages.

If you are opting for a simple API key to authenticate web service clients that is passed as a URL param or in the HTTP header, be aware that API keys would need to be well protected in the mobile application package. Android apks, for example, can be easily unzipped and your API key can be extracted.

Validate API Input Parameters

Also a no-brainer, of course. For security and data integrity reasons, every input parameter to your web service methods should be validated. Make sure the parameter is not empty and adheres to the data type’s format. For example, make sure an email address has a valid format.

In case any input is invalid, return a BadRequest (400).

Use JSON as data structure format

Cell phone users on 3G may only have a data transmission rate of 200 Kbps. In order to build fast, responsive mobile apps, the flow of data to the device needs to be fast.

Using JSON to format data passed from the app to your web service and vice versa has an advantage of lowering your network payload by about 30%. This is due to the fact that JSON does not repeat the node names for their node tags.

An additional tip is to compress requests before transfer and responses before sending them using a compression library such as gzip. It takes a little more implementation effort but it may be worth it if you have to transfer a high volume of data to or from the app.

Use well-known HTTP Response Codes consistently

Nobody expects us to implement all 3 million HTTP status codes, but I’d like to stick to the most important ones and use them consistently and correctly.

Here a list of the most important ones:

  • 400 Bad Request. …
  • 401 Unauthorized. …
  • 403 Forbidden. …
  • 404 Not Found. …
  • 500 Internal Server Error. …
  • 502 Bad Gateway. …
  • 503 Service Unavailable. …
  • 504 Gateway Timeout.

More about HTTP Status codes here.

Structure Request/Response Formats

It pays off in the long run to put some thought into structuring requests and response formats between web service APIs in a standardized way.

For example, instead of creating a different format for every request action, you may want to create one request class per entity and use it for all of your API actions. The request payload could be a list of objects of that type.

For example, to create a User, your request could contain a list of Users but you only add one. When you send an update request, you use the same request with one user in the list.

To structure responses, I see two main options: First, you can create a response class that includes both the data and an error code and error message if needed. The advantage of this approach is that you can deserialize the response to the same response class no matter if the server returned a successful or a failed response.

The second option is to keep your data and your error messages apart. Create one response class that returns a list of your data in case the web service call was successful. A second response class that contains a list of errors.

Then, in your mobile app, you can determine which response will be received by evaluating the HTTP status code. If the status code is 200 (OK), you know the response will contain data. If the status code is an error code, you know the response will be one or multiple errors.

I personally prefer the second approach since I find it more clean to separate the two types of data.

Standardizing Error Codes

In my view returning an Error Code along with an error messages from your web service is a good idea. Especially for larger implementations, where you may have multiple similar error messages, using an error code returned to the app can help you to quickly identify the exact error that occurred inside your web service.

I recommend implementing all error codes along with their meaning in one class as a constant.

As an alternative, you could implement them in a JSON file that can be shared between on the app code and server code.

As a naming convention for error codes you could use:

<HTTP status code> + <index>

For example, for error messages related to bad requests, you could use:

4001 : Invalid email address, 4002 : Invalid user name, etc.

That way, just by looking at the first three digits of the error code, you know what type of error message it is.

Use Language Localization Files

Your web services may create error or informational message that will be displayed to the user inside your app. Initially, you may start implementing your app only in English language. However, as your app becomes more popular, you may want to add other languages to the mix.

Don’t hardcode all your error message in one language inside your web service controller. Create language files and let the controller resolve the error string based on a constant.

For example, in .Net you can create a resource file which is a dictionary of key/value pairs that can hold your language-specific error messages. Next, you implement a StringLocalizer that fetches.

In order for your web service to figure out which language to pick, you could pass the language as a HTTP header parameter from your app or as part of the HTTP user agent.

Implement Logging using a Logging framework

It sounds like a no brainer but when project deadlines are moving up, this point get easily forgotten. I have worked for a Fortune 500 company and was surprised they had not implemented logging in their web services. So now a web service call started taking 10 minutes to complete and they had no idea what was going on.

So select a well-known logging framework library for your implementation and add the ability to log to file or the system log with different log levels. Next, implement debug log statements so if there’s an issue, you can turn on debug logging and figure out what the heck is going on.

Use DTO and DOAs

Data Transfer Objects (DTO) and Data Access Objects (DOA) are two useful design patterns that facilitate data retrieval from whatever data sources you need to interface with.

DTOs are containers that can be used to move data between your web service application layers.

For security and memory management reasons, these objects may only contain the sub-set of the actual data stored in the database associated with your entities.

For example, let’s say you want to expose a service method that updates a user’s membership state. There is no reason to fetch the user’s confidential data (e.g. address, DOB, SSN) from the database and expose it to the API controller. Instead, you can use a DTO to update the user’s membership status or fetch only the most important information you need to get the job done.

DOA’s expose standard methods to the business logic to access the database and perform operations on the different entities you are dealing with. By standardizing these methods, you can reuse them for different web APIs.

Here a simple example of a DTO and DTA for a User entity:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class UserDTO{
   public string firstName = "";
   public string lastName = "";
   ...
}
interface IUserDOA{
   UserDTO getUser(string userId);
   bool updateUser(UserDTO userDTO);
   ...
}
class UserDOA implements IUserDOA{
  UserDTO getUser(string userId){
    // implement db access
   }
   bool updateUser(UserDTO userDTO){
     // implement db access
   }
   ...
}

Keep Controller Implementation Flat

Sometimes you may see API Controller implementation where the complete business logic is implemented in the controller code. As the business logic becomes more complex, the controller code becomes larger and harder to maintain.

Following the OO principles of Abstraction and Encapsulation, move your business logic implementation from the controllers into supporting classes, e.g. if your API creates a User Account, create a UserAccountService class that handles all the heavy lifting.

Keep your controller code nice and flat. Only perform input parameter validation, call the main methods of your services, and process results from the services.

Use Dependency Injection

Dependency Injection is a ‘bread-and-butter’ design pattern that you want to use for your web service implementation. In means that instead of instantiating dependent entities inside a class, the dependent entities are injected into the class from outside, either via the class constructor or a method.

For example, if you create a service that is responsible for fetching database information, you could inject the object that interfaces with the database into your service.

The advantages of this pattern is that they decouple classes, improve flexibility in swapping out modules to improve testing, configuration, refactoring and support the overall maintainability of the system.

There are a lot of libraries that simplify dependency injection for you and automatically map, resolve and inject. For example, in .Net Web API implementations you could use Unity. In Java implementations you could use Dagger or Spring DI.

More about Dependency Injection here.

Creating Adapters to external services

In case your web services utilizes other external services, I suggest to use the Adapter design pattern to implement the interface. This way, if the external service changes, your web service changes and retesting will be minimized.

For example, let’s say your web services uses Amazon AWS databases to store user data. Your company decides to switch cloud providers and you need to interface with Microsoft Azure. If you use the Adapter pattern to implement your cloud service interface, the change should be a piece of cake.

The Adapter pattern consists of one interface that implements all the methods you need and a class that implements the interface on the side of the web service. Next, there is the Adapter class that implements the interface and ‘translates’ it to the externally facing implementation which also consists of an interface and a class that implements the interface.

Let’s say your web service is using a cloud database for storing user account information. Then you could create a service that handles all user account actions. The interface between the web service and the cloud database could be implemented as an adapter pattern in case you want to switch to a local database or another cloud service in the future.

Here the sample implementation:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// Internal Facing Interface
interface IUserAccountService{
  bool createUser(User user);
  bool updateUser(User user);
  ...
}
class UserAccountService implements IUserAccountService{
    IUserAccountService Adapter adapter;
    bool createUser(User user){
      adapter.createUser(user);
    }
    bool updateUser(User user){
      adapter.createUser(user);
    }
}
class UserAccountServiceAdapter implements IUserAccountService{
   AzureAccountService azService = new AzureAccountService ();
    bool createUser(User user){
      AzUser azUser = new FbUser(user);
      azService .createAzureUser(azUser );
    }
    bool updateUser(User user){
      AzUser azUser = new AzUser(user);
      adapter.updateAzureUser(azUser );
    }
}
// External Facing Interface
interface IAzureAccountService{
  bool createAzureUser(AzUser user);
  bool updateAzureUser(AzUser user);
  ...
}
class AzureAccountService implements IAzureAccountService{
 
    bool createUser(AzUser user){
      // implementation
    }
    bool updateUser(AzUser user){
      // implementation
    }
}

More about the Adapter design pattern here.

Client-Side Best Practices

Validate User Input

In order to avoid security and data issues due to bad user input, I suggest to implement strict user input validations in your UI layer. Make sure that email addresses have a valid format, that passwords match your password rules, that data doesn’t contain unwanted characters and that it doesn’t exceed maximums used in your database.

By implementing validations on the app side, you are already filtering out a lot of unwanted crap before sending it to your web service.

The web service should implement additional input validations for the same reasons.

There are several third party / open source validation libraries available and simplify validation of the most common data formats.

Use a Library for Authentication

If you decided to implement an authentication protocol for your web services like OAuth, I would strongly advise you against trying to implement the protocol inside your app yourself. No need to reinvent the wheel.

Instead, use an open-source or commercial library from a well-known source, meaning a Fortune 500 or NASDAQ company, not some dude straight out of high-school that put a lib out on GitHub. I just spent the last three months replacing server-side and client-side open-source libraries that sucked and had a lot of issues – so that’s my lessons learned.

Use a Parsing Library To Parse Responses

If you are even considering processing server-side JSON responses using pattern matching, you’re out of your mind. The whole purpose of using a structured format like JSON for data exchange is so you can use a parser library for processing.

So I suggest to use a JSON parser library like Newtonsoft’s JSON parser on Android or SwiftyJSON on iOS to make your life easier.

And don’t forget to catch JSON parsing exceptions in case the JSON response payload from the server is somehow not valid.

Implement HTTP client Exception Handling

HTTP clients throw exceptions. Happens all the time. Network’s down -> http client throws an exception. A web service times out -> http client throws and exception. Network can’t get a route to the destination -> http client throws and exception. I worked on a project once and 80% of the app crashes came from unhandled http client exceptions.

I suggest to create a wrapper class around your HTTP client and place try/catch blocks around every http request.

Implement Exception Handling in Response Processing

Web Services aren’t perfect and as a mobile developer, I have to anticipate that a web service gives me a) something that doesn’t make any sense, b) total crap, or c) nothing at all.

So make sure you catch any parsing- or processing exceptions whenever responses from the server are being processed by enclosing them in a try/catch block.

Also, be aware on which thread server responses are returned. For example, on Android using OKHttp client, asynchronous are returned on a background thread. If you want to update the UI, you have to make sure you make those updates on the UI thread.

Use a modern Networking Library

Most mobile development SDKs offer some way to send HTTP requests. However, sometimes the SDK networking functionality is rather basic. In order to implement more advanced features such as thread pool management, caching, error processing, retry, etc. you would have to do some serious coding.

Modern networking libraries such as Retrofit or Volley on Android and AFNetworking on iOS offer some or all of these features. I suggest to review the features of each library and decide which one is suitable for you.

Author Description

justmobiledev

No comments yet.

Join the Conversation