Once you’re familiar with the syntax and basic concepts, you can start thinking about asynchronous Rust. Most modern languages have a build in runtime that handles asynchronous tasks, such as sending off a request or waiting in the background for an answer.
Tokyo is the most production-used and proven runtime that can handle asynchronous tasks, so chances are high that your future employer already uses it. Your choices are therefore somewhat limited since you may need to choose a library that already has Tokyo built in to create your API.
Depending on your previous programming experience, it may take a few days to wrap your head around it. But once you understand warp, it can be quite an elegant tool for building APIs.
Warp for creating the API Tokyo to run an asynchronous server Serve to help serialize incoming JSON parking_lot to create a ReadWriteLock for your local storage So when you start the server via cargo run and point your browser to localhost:3030/hello/WHATEVER, warp sends this request through its filters and executes the first one that is triggered.
If we point the browser to localhost:3030/hello/new/WHATEVER, we’ll get a 404 since we don’t have a filter for /hello/new + String. In addition to routes, we need to store a state in a file or local variable.
In an asynchronous environment, we have to make sure only one method at a time can access the store so there are no inconsistencies between threads. In Rust, we have Arc so the compiler knows when to drop a value and a read and write lock (Rowlock).
To add items to the list, make an HTTP POST request to a path. Our method has to return a proper HTTP code so the caller knows whether their call was successful.
Warp offers basic types via its own HTTP library, which we need to include as well. Since you can expect a JSON for this, you should create a little json_body helper function to extract the Item out of the body of the HTTP request.
Start the server via cargo run and open another terminal window or tab to execute the following curl. You’ll get a taste of asynchronous Rust when you examine the data structure behind your Arc.
You’ll need to .read() and then .inter() over the data inside the Rowlock, so create a new variable to return to the caller. Due to the nature of Rust ’s ownership model, you can’t simply read and return the underlying list of groceries.
Then, iterate over the Yashmak and write every key/value pair into a new one, which you’ll return via warp::reply::Jason(). Here the Rust Yashmak implementation uses.insert() as well, but it updates the value instead of creating a new entry if the key doesn’t exist.
We would need to implement proper error handling in case we pass the wrong JSON format to the server. If you’re interested in monitoring and tracking performance of your Rust apps, automatically surfacing errors, and tracking slow network requests and load time, try Rocket.
Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. Photo by Markus Spike on Unsplash Rust has been around for about 5 years.
Is a language that claims to be “memory-safety” and performs extremely fast. Is a multi-purpose language and comes with built-in functionality for command line, web assembly, networking, and embed applications.
In the following steps, I am assuming that you already have Rust and Cargo (rust up) fully installed and running. Diesel is an extensible ORM and query builder for Rust.
I believe that having smaller files and separated by responsibility is good for maintenance and is an easier way to organize your projects. So to follow the next steps you should have in your project directory a migrations' folder.
In these items.rs the file is the handler function to list, delete, and create new items. Developing APIs with rust can be very time-consuming when comparing with other languages and frameworks.
And using the same database we will compare the same results from an API build in PHP with the lumen framework. Rust is incredibly quick by doing it in a quarter of the time that lumen need to do it.
In my opinion, it's not fair to compare lumen with rust. I'm starting to get fascinated with rust and it’s running speed is impressive.
There are quite a few frameworks that make it easy to create a RES TAPI by reducing the number of boilerplate. I personally prefer Rust because it is simple, strongly typed, extremely fast, and safer than almost any language out there.
In this tutorial, we’ll demonstrate how to write simple endpoints, handle errors, maintain a connection to the database, persist data to Postgres DB, and, eventually, handle the request-response cycle. I chose the Act ix web 2.0 framework because it’s one of the most popular, has great documentation, and uses patterns similar to TypeScript Express in Node.js.
Our persistence layer will consist of Postgres with Diesel as the ORM and query builder. Before we dive into coding, let’s take establish what we’ll be building and some fundamental requirements and assumptions.
To proceed with this tutorial, you’ll need a basic understanding of API development. I’ve written this guide to be easily understood by anyone with a basic understanding of the Rust language.
First, let’s go over how to set up a basic Rust project, folder structures, dependencies, etc. You’ll already be familiar with NPM as the package management and registry.
Let’s set up a very basic route handler to ensure that everything works before moving forward. Inside main.rs, which is the entry point for the application, pull in the act ix crate.
In Node, you’d fix this problem by watching for changes with no demon. Imagine a situation in which a request is sent to your API during compilation, and the REST client just breaks off without any useful information.
To ensure that the connection remains open and that we can respond to a request as soon as recompilation is complete, we’ll introduce the system crate by running the following. Now run the code in watch mode so you don’t have to kill and restart the server after every modification.
Now that you have the initial setup running and can confirm the modest server is up, you can proceed to create real API endpoints. Since you’re running cargo-watch, you don’t need to rebuild; Cargo recompile automagically.
Here we imported the serve crate’s Serialize and Deserialize annotations, respectively, which are responsible for converting our model from and to JSON. Next, you’ll need to persist your data and respond to clients’ CRUD requests when they hit your endpoints.
At first, you can respond with hard coded data to make sure things work, then add persistence with Postgres. Your next task is to connect to a real database and expose the model as a crate to other programs within your application outside the employees' directory.
Nothing has changed except that you’re replacing your dummy endpoints with a more dynamic mapping, which happens within route.rs. A bunch of API endpoints without the ability to persist data is not fascinating.
Diesel, which claims to be “the most productive way to interact with databases in Rust because of its safe and composable abstractions over queries,” has two major dependencies that you’ll need to have installed before you can use its CLI: OpenSSL and the Postgres library itself. Now that you have your dependencies updated, it’s time to set up Diesel in your project.
Inside src/migrations/~/up.sql, create a table named employees to hold data for your notes. Now that you’ve created the employees' migration, it’s time to run it with the Diesel CLI.
If you run the above command, you’ll get an error asking for a database URL. You’ll notice that this does not have an id property since this is automatically generated.
In find_all, for instance, like all other methods, we connected the database with let Conn = db::connection()? If you run the cargo watch command we went over earlier, you should be able to create, read, update, and delete (CRUD) an employee from the database through your API endpoints.
You should now understand how to create API endpoints and handle a simple request response cycle in Rust using Act ix. We covered how to build endpoints to handle the fundamental CRUD operations, manage data persistence with Diesel as the Postgres ORM, and handle and respond to errors with an error handler.
What I really like about building APIs with Rust is that it enforces good practices by engaging you to think critically about your code. If you’re interested in monitoring and tracking performance of your Rust apps, automatically surfacing errors, and tracking slow network requests and load time, try Rocket.
Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred.