MARS client library: Accessing error response
Basic error signaling in REST API are usually driven by HTTP status codes (eventually also using the HTTP reason field, even if its purpose is tied to CORS implementation). This is generally handled causing an exception in http client libraries (like MARS Client Library, Indy, REST Client library and others).
However, it is not uncommon that REST application servers will provide an http error together with a response body (possibly valid JSON) describing the error or instructing the client in some (custom) way.
One of MARS users (thank you, Kostas, you always come up with interesting requests) asked me how to access that response using the MARS Client Library (that is an agnostic REST client library so it can be used against non-MARS REST servers). It was already possibile since long time to access the response content when an exception (caused by the server error) was thrown but I’ve decided to add a couple of (useful) shortcuts to make things easier for the client developer. Check the ErrorObjects demo in MARS Github repository.
In short, here a simple example:
MyResource.GET(
nil
, procedure (AResponse: TStream)
begin
// OK, successful request, AResponse is the actual response
end
, procedure (AException: Exception)
begin
// ERROR: the server returned a non 200 http status code
if (AException is EMARSClientHttpException) then
begin
var LException := EMARSClientHttpException(AException);
// let say this API returns a JSON object as error response
var LJSON := LException.ContentAsJSON as TJSONObject;
try
// do something with the error JSON object
finally
LJSON.Free;
end;
end;
end
);
The EMARSClientHttpException (MARS.Client.Utils unit) exception class was already providing access to the underlying http response but now it features some more handy properties like:
StatusText: string
StatusCode: Integer
Content: TMemoryStream
ContentType: string
ContentAsString: string
ContentAsJSON: TJSONValue
ContentAs<T>: T
ContentAsArrayOf<T>: TArray<T>;
If the Content property will grant you a generic TMemoryStream reference, ContentAsJSON will let you greatly simplify your client’s code. The same stands for ContentAs<T> and ContentAsArrayOf<T> where T can be a record type and you’ll take advantage of MARS Client JSON deserialization capabilities.
In the next blog post we will delve into the twin feature I’ve implemented in MARS server in order to provide error responses.
Sincerely,
Andrea