I'm pleased to announce the release of 0.9.0 of librest, a library meant to interact with "Restful" web services. This library is very old and not really big but it handles the aspect of interaction with REST-APIs in a convenient fashion. After a long period of maintenance state i picked it up and brought it into 2022. Most of the deprecated API calls are gone now and it should be now possible to parallel-install librest with the previous release.
Basically its an abstraction of
libsoup which is an HTTP client. If you would use
libsoup directly it happens to create some kind of abstraction is necessary for your usecase in order to encapsulate all REST functions with their necessary HTTP calls. Here ´librest` tries to help by providing an abstraction fitting to the REST usecase in general.
Typically a REST interface contains the host on which data need to be fetch/posted and a function.
librest encapsulates the host in a
RestProxy. Every call to the REST interface starts from there. The creation is a simple
RestProxy *proxy = rest_proxy_new ("https://www.gitlab.com/api/v4/", FALSE);
It is possible to make the host parametrizable. For example if we want to support different API versions it is possible to do something like this:
RestProxy *proxy = rest_proxy_new ("https://www.gitlab.com/api/%s/", TRUE);
I will describe later how to fill in the void of
%s in order to choose which API version we want to target.
In order to call now a function of the host we create a new
RestProxyCall *call = rest_proxy_new_call (proxy);
Of course this object needs now some configuration in order to call the correct function we need.
rest_proxy_call_set_function (call, "version");
If you did created a parametrizable proxy you should bind the proxy before creating a new call:
rest_proxy_bind (proxy, "v4");
Ok we have now everything configured so we can execute the call:
// sync variant GError *error = NULL; rest_proxy_call_sync (call, &error); // or async variant rest_proxy_call_invoke_async (call, cancellable, my_callback_when_done, user_data);
We see its possible to call the REST interface in a blocking and in an unblocking variant (GUI tools should use the later)
By default a
RestProxyCall calls the REST interface via
GET in order to fetch data. Of course its possible to use other HTTP methods too via:
rest_proxy_call_set_method (call, "POST");
If you want to add query parameters or payload to your call just use the params-interface:
rest_proxy_call_add_param (call, "key", "value");
Depending on the HTTP method this will be transformed to a query or a payload.
When a call is successfully you can inspect the response from the server via:
const gchar *payload = rest_proxy_call_get_payload (call); goffset payload_length = rest_proxy_call_get_payload_length (call);
NOTE: the payload string is not null terminated as its contained in a GBytes structure. Therefore it is always recommended to use the length too. Transforming it to a null terminated string can be done via:
gchar *payload_null_terminated = g_strndup (payload, payload_length);
Most REST APIs need some sort of authentication. Sadly the HTTP authentication workflow with a unauthenticated call -> respone 401 -> try basic/digest auth -> response 200 does not work because its possible to call some REST APIs also as unauthorized user.
Besides of that problem it is most often not perfect security therefore there are many more options API provider can choose. For example it is possible to secure the API with OAuth/OAuth2. Both are possible wit
librest but it is necessary to use the specified Proxies for these authentication methods.
// OAuth 1.0 or 1.0a oauth_proxy_new (consumer_key, consumer_secret, url, binding_required); // OAuth 2 rest_oauth2_proxy_new (authurl, tokenurl, redirect, client_id, client_secret, url);
The former was already present in earlier versions of
librest. I wanted to keep the namespace intact which is the reason that OAuth2 uses an prefix
I continue working on that nifty little library as i think its an important part of todays communication possibilities. I will try to reduce the code in GNOME Online Accounts because they have to maintain already the same functionality which perfectly would fit into librest.