Implementing HTTP status codes when exposing a REST API in OutSystems
All images are property of their respective owners.

Implementing HTTP status codes when exposing a REST API in OutSystems

Continuing from my last article "Handling HTTP status codes when consuming a REST in OutSystems", today we take the exposing an API perspective.

A very interesting read for some conceptual background is the "RESTfull API Design: What About Errors?" from Google/apigee blog post, which we will use as a guide for this exercise.

apigee has some very interesting e-books dedicated to API building, including Brian Mulloy ebook "Web API Design - Crafting Interfaces that Developers Love".

Concepts

As Brian Mulloy points out on his blog, the API that you are designing is a black box for developers and most prefer a trial and error approach. These two reasons make it very important to communicate errors in a clear and rich way.

Also mentioned on the ebook the most popular API's out there use 3 distinct patterns:

  • Abstract error message and usage of an HTTP status error code
  • Rich error message and usage of an HTTP status error code
  • An error message but always returning HTTP 200 success code

Best Practices

Brian Mulloy recommends we use HTTP status codes and map them to the standard meaning. There are plenty of flavors for our needs (check the wiki) including the iconic HTTP 418 I'm not a teapot.

We should at least implement 3 codes:

  • 200 - OK (all is good)
  • 400 - Bad Request (client did something wrong)
  • 500 - Internal Server Error (API did something wrong)

From here we can expand in details. Any OutSystems API implements these Built-in HTTP Status Codes: 200, 400, 401, 403, 404, 405, 406, 415 and 500. However, most of them are tied to specific platform events and can be customized to our needs.

For example, a "404 Not Found" is returned by OutSystems if a REST API method is not found, however, you can still raise a 404 if the result of a query is empty.

Anatomy of a REST call in OutSystems

No alt text provided for this image
  1. Security Validations: After receiving the REST API Method request, OutSystems executes the security validations according to the settings in REST API properties HTTP Security and Internal Access Only;
  2. OnRequest(): OnRequest callback allows you to run logic over the requests after receiving them;
  3. OnAuthentication(): OnAuthentication callback allows you to add basic authentication or custom authentication to requests;
  4. Parameters Deserialization and Validation: Deserialization of the input parameters and validation of the data types, mandatory values, etc;
  5. Execute Method: Executes the action that implements the REST API Method;
  6. Parameters Serialization: Serialization of the output parameters to return in the response;
  7. OnResponse(): OnResponse callback allows you to run logic over the responses before sending them. It is always executed, even in an error situation.

Step 1 - Take control over the OutSystems exception handling

OutSystems uses the following HTTP status codes when working with exposed REST API methods.

This should be enough for our needs, but we do want to take a step further and present a nice rich error detail response and also be in total control when to raise the exception.

The default exception for REST is represented by:

{

    "Errors": [

        "The 'Id' URL parameter is missing in the request.",

        "The request body is missing."

    ],

    "StatusCode": 400

}

But we want to add some richness to it, something like: 

{"HTTPStatus": {

    "HTTPCode": 404,

    "developerMessage": "Not Found",

    "userMessage": "The server can not find the requested resource. In the browser, this means the URL is not recognized. In an API, this can also mean that the endpoint is valid but the resource itself does not exist. Servers may also send this response instead of 403 to hide the existence of a resource from an unauthorized client. This response code is probably the most famous one due to its frequent occurrence on the web.",

    "errorCode": "404",

    "moreInfo": "For more information please visit https://en.wikipedia.org/wiki/List_of_HTTP_status_codes"

  }
}
}

So, we start by creating this structure, including it on our API response and a user exception, in our case REST.

No alt text provided for this image


No alt text provided for this image

After this, let's create a generic method to raise the exception. (please note that the odd display of the flow is just to make it look better on a document)

No alt text provided for this image

Step 2 - Implement the exceptions

So let's walk through the exception implementation.

Authentication

No alt text provided for this image

The first thing to run is the authentication check. Whatever authentication method you're using, just raise the appropriate exception if it fails. Note the exception is raised by the generic method created above.

No alt text provided for this image

From this point on you just need to replicate the same concept for Authorization, Request format and the exceptions coming from the implementation itself.

No alt text provided for this image

Authorization

No alt text provided for this image

Request Validation

No alt text provided for this image

Inside the implementation

Here is where you surface the exceptions coming from the implementation into the API itself.

No alt text provided for this image

I went a bit overboard with this by actually translating the exceptions coming from the implementation into API exceptions.

No alt text provided for this image

This is done by catching all exceptions on the public actions of the implementation, identifying them, and re-raising them as REST user exceptions from this module.

No alt text provided for this image

Step 3 - Customize the Response

Create a generic action to handle the customized response.

No alt text provided for this image

The following may look a bit complex but it is actually straightforward:


  • Check if the response is an exception or a normal response
  • If normal response just let the request go forward
  • In the example, a simple Deserialize works fine but your mileage may vary
  • Check if the exception is a standard exception or a rich exception
  • If standard then parse it into a rich exception
  • Parse the rich exception into JSON
  • Send the JSON back to the client
No alt text provided for this image

Playing with the Example

 You can try it out here.

No alt text provided for this image

 Or use a few simple HTTP requests:

Get the Component  

I’ve published the component in the OutSystems Forge.

No alt text provided for this image

Give it a try, and go create those APIs.

disagree about 404 (NOT FOUND) - it pretty clear it's about server not being able to process a URI, cause there is no representation behing it, it's in status specification,

Like
Reply

Great documents Rui. Will reuse it for sure in our best practices! Cheers!

How is this better than native code?

Like
Reply

To view or add a comment, sign in

More articles by Rui Barbosa

Others also viewed

Explore content categories