api_builder 0.1.1

A simple client-agnostic API builder, inspired by the GitLab crate
Documentation

API Builder

This crate aims to make it easy to build API bindings in Rust. It is inspired by gitlab and how they build their API bindings.

For some examples, especially on the macros, view examples.

The ideology

The contents of the entire HTTP request, minus authentication (see handling authentication), is within a single endpoint struct. From there, users can supply their own client, response type, and other handlers via combinators. Therefore, your bindings will not lock users to a specific HTTP client and can customise the client and response to fit their needs.

The benefits

  • It's more "rusty"
  • Users can use both async and synchronous methods
  • Easy testing via mock client implementations
  • Customisable behaviour
    • Custom response type
    • Bring Your Own HTTP Client
    • Supports "middleware" via combinators and custom clients

Handling authentication

Authentication is sensitive and if the bindings you make are supposed to be consumed directly by the user, you might not want them to supply their API token each time. While that approach is perfectly fine, it can be tedious and the behaviour can be abstracted to your own client which handles it all.

For example, you can make your own client skeleton which stores the API token and a user-supplied sub client. From there, you implement RestClient and forward that implementation to the inner sub client. However, you add custom logic to Client::rest/AsyncClient::rest_async which would add the corrosponding authentication headers. Now, you can remove the API token from the endpoint struct and force users to use your client skeleton.

Alternatively, you can make your own combinator which takes in the endpoint and any tokens. The combinator approach might make it easier when these tokens are directly present in the body of the request, but you don't want to include them in the endpoint struct. However, this shifts the original problem to another place, and that's why I prefer the client route.

For a full example of the client approach, you can read luarmor-rs.

Additional advice