Introduction: Why Rust for REST API?
\nRust is a modern systems programming language that combines the performance of C/C++ with memory safety without a garbage collector. For creating REST APIs, Rust offers several powerful frameworks, and Actix-web is one of the most popular. In this guide, we will create a full-fledged REST API in Rust step by step in 30 minutes. You will see how quickly you can get started, even if you are a beginner in Rust.
\n\nEnvironment Setup
\nBefore writing code, make sure you have Rust installed. If not, run the command:
\ncurl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh\nAfter installation, check the version:
\nrustc --version\nNow create a new project:
\ncargo new rust_rest_api\ncd rust_rest_api\nOpen the Cargo.toml file and add dependencies:
[dependencies]\nactix-web = "4"\nserde = { version = "1.0", features = ["derive"] }\nserde_json = "1.0"\ntokio = { version = "1", features = ["full"] }\nRun cargo build to install all packages. This will take 1–2 minutes.
Creating a Basic REST API in Rust
\nLet's start with a simple endpoint that returns a greeting. Open src/main.rs and write:
use actix_web::{web, App, HttpServer, Responder};\n\nasync fn hello() -> impl Responder {\n "Hello, world! This is a REST API in Rust!"\n}\n\n#[actix_web::main]\nasync fn main() -> std::io::Result<()> {\n println!("Server running at http://127.0.0.1:8080");\n HttpServer::new(|| {\n App::new()\n .route("/", web::get().to(hello))\n })\n .bind("127.0.0.1:8080")?\n .run()\n .await\n}\nRun the server with the command cargo run and open http://127.0.0.1:8080 in your browser. You will see our greeting. This is the foundation of any REST API in Rust.
Adding Data Structures and JSON
\nA real REST API works with JSON. Let's create a user model and an endpoint to retrieve it:
\nuse serde::{Deserialize, Serialize};\n\n#[derive(Serialize, Deserialize)]\nstruct User {\n id: u32,\n name: String,\n email: String,\n}\n\nasync fn get_user() -> impl Responder {\n let user = User {\n id: 1,\n name: "Ivan Petrov".to_string(),\n email: "ivan@example.com".to_string(),\n };\n web::Json(user)\n}\n\n// In main() add a new route:\n// .route("/user", web::get().to(get_user))\nNow at the /user address you will receive a JSON object. This is a key point: Rust automatically serializes the structure into JSON thanks to serde.
Working with Query Parameters and POST Requests
\nA real API should handle different HTTP methods and parameters. Let's add an endpoint for creating a user via POST:
\nuse actix_web::web::Json;\n\nasync fn create_user(user: Json<User>) -> impl Responder {\n let new_user = user.into_inner();\n println!("User created: {} ({})", new_user.name, new_user.email);\n web::Json(new_user)\n}\n\n// In main():\n// .route("/user", web::post().to(create_user))\nNow you can send a POST request with a JSON body, for example, via curl:
curl -X POST http://127.0.0.1:8080/user \\\n -H "Content-Type: application/json" \\\n -d '{"id":2,"name":"Maria Smirnova","email":"maria@example.com"}'\nThe server will return the same object, confirming the creation. This is the basis for CRUD operations.
\n\nHandling Path Parameters and Query Strings
\nLet's add an endpoint to get a user by ID via a path parameter:
\nuse actix_web::web::Path;\n\nasync fn get_user_by_id(path: Path<u32>) -> impl Responder {\n let user_id = path.into_inner();\n // In a real application, this would be a database query\n