Lessons learned from buying, connecting, and operating domains
Free Trial
Updates

Introducing the new Rust REST API Client Library

Enrique Comba Riepenhausen's profile picture Enrique Comba Riepenhausen on

Domain Management Automation is one of the main focuses at DNSimple. It's part of our vision for providing a comprehensive set of tools and services to manage your domain infrastructure. You can integrate directly with our REST API using one of our many API clients we've been (and continue) developing over the years.

If you're a reseller, our REST API offers a big advantage – companies that resell domains can automate the whole process using our reseller plan.

We decided we wanted to release a new DNSimple API client at the beginning of 2022. We considered a variety of languages, eventually deciding on Rust. For our Python and PHP developers, we've also moved those clients out of Beta – you can read more about our REST API here.

Why Rust?

We wanted to bring you an exciting language that's been gaining traction in the dev community. A few team members mentioned Rust and pointed out the many great features the language offers.

The Rust language was created to be high performing. It's comparable to the performance offered by C and C++, while emphasizing the code's safety – the achilles heel of the other two languages.

Working with Rust

Rust is different from many languages, and there were some challenging concepts along the way. Let's talk about some of those, and their solutions, to give you a glimpse into our latest REST API client.

One of these gotchas was that Rust arguments pass into a function to move away from your current scope and become unavailable to the rest of the function you're in. You have to be careful when thinking about references, copies, and ownership.

When we start a new client, the first thing we try to do is to write as many learning tests as possible. Doing this, we learn how to write unit tests, what the collection types are, other pieces of the language itself, and whether we need a third-party library to do some of the tasks (with Rust it was mainly sending HTTP requests and parsing JSON). Then we focus on the general structure of the client.

We need a system that allows us to create the necessary endpoints as fast and efficiently as possible. This looked something like:

Defining an Endpoint trait, which defines an Output

pub trait Endpoint {
    type Output: DeserializeOwned;
}

This lets us define the functions to perform HTTP requests in a fairly elegant way:

pub fn get<E: Endpoint>(
    &self,
    path: &str,
    options: Option<RequestOptions>,
) -> Result<DNSimpleResponse<E::Output>, String> {
    self.call::<E>(self.build_get_request(&path, options))
}

Which then, when creating an endpoint, makes things much easier.

Let's look into the Identity (/whoami) endpoint of our API.

We first need to define the Endpoint Struct:

struct IdentityEndpoint;

impl Endpoint for IdentityEndpoint {
    type Output = WhoamiData;
}

The Output of this struct is another struct (WhoamiData) that contains the attributes related to the JSON payload returned by our API when you request your identity using the /whoami endpoint.

The Identity struct has one public function (/whoami), which will perform the get request to the API server and return a Result struct containing a DNSimpleResponse struct with all the necessary data inside.

pub fn whoami(&self) -> Result<DNSimpleResponse<WhoamiData>, String> {
    self.client.get::<IdentityEndpoint>("/whoami", None)
}

It was well worth spending the time (and refactoring over and over; rinse, repeat) to get to this point. It allowed us to fly over the endpoints at breakneck speed once the pattern emerged.

Getting started with DNSimple's Rust API client

Let's look at some examples:

We'll start with the identity service – you've already seen (partially) how it looks inside:

use dnsimple::dnsimple::{Client, new_client};

let client = new_client(true, "AUTH_TOKEN".into());
let identity = client.identity().whoami().unwrap();
let data = identity.data.unwrap()
let account = data.account.unwrap();
let account_id = account.id;
// account.email => "your_account@email.com"

Listing your domains is just as easy:

let response = client.domains().list_domains(account_id, None).unwrap();
let domains = response.data.unwrap();

Want to create a domain?

let response = client.domains().create_domain(account_id,"example-domain.com".into()).unwrap();
let new_domain = response.data.unwrap();

There are lots of other examples in our developer documentation and in the official dnsimple-rust documentation.

Make sure you check out our new Rust REST API client! And as always, feel free to get in touch with any questions you might have – we're always here to help.

Ready to try our domain management automation and REST API clients for yourself? Give us a try free for 30 days.

Share on Twitter and Facebook

Enrique Comba Riepenhausen's profile picture

Enrique Comba Riepenhausen

Father, coffee aficionado, nomad and motorbikes. When he's not helping developers and customers succeed in their businesses, you can find him on his motorbike exploring the world.

Try out DNSimple free for 30 days
DNSimple logo

We provide worry-free DNS services to simplify your life.

Try us free for 30 days