Making JSON webapi server with Rust and Rocket
# rustup.
$ curl https://sh.rustup.rs -sSf | /bin/bash -s -- -y --default-toolchain nightly
$ cd rocket-webapi
$ cargo run
Configured for development.
=> address: localhost
=> port: 8000
=> log: normal
=> workers: 8
=> secret key: generated
=> limits: forms = 32KiB
=> tls: disabled
Mounting '/':
=> GET /
=> GET /todos
=> GET /todos/<todoid>
Rocket has launched from http://localhost:8000
Hello, world!
http://localhost:8000
Get all ToDOs
http://localhost:8000/todos
Get ToDO by ID
http://localhost:8000/todos/10
RustCC++10C++MMOC++17Modern CMakeRangeRustC++Rust()C++23SaneRust()
RocketRustPythonFlaskTODOWebAPIRocket
Hello, world
$ cargo new rocket-webapi
$ cd rocket-webapi
rust-toolchain
nightly
Cargo.toml
[package]
name = "rocket-jsonapi"
version = "0.1.0"
[dependencies]
rocket = "0.4"
rocket_contrib = { version = "0.4", features = ["json"] }
src/main.rs
#![feature(proc_macro_hygiene)]
#![feature(decl_macro)]
#[macro_use]
extern crate rocket;
/// GET"Hello, world!"
#[get("/")]
fn index() -> &'static str {
"Hello, world!"
}
fn main() {
rocket::ignite()
.mount("/", routes![index]) //
.launch();
}
$ cargo run
Configured for development.
=> address: localhost
=> port: 8000
=> log: normal
=> workers: 8
=> secret key: generated
=> limits: forms = 32KiB
=> tls: disabled
Mounting '/':
=> GET /
Rocket has launched from http://localhost:8000
$ curl http://localhost:8000
Hello, world!
(^o^)
# Rust toolchain
rustup update
ToDoWebAPI
Cargo.toml
[package]
name = "rocket-webapi"
version = "0.1.0"
[dependencies]
rocket = "0.4"
rocket_contrib = { version = "0.4", features = ["json"] }
# serdecrate
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.0"
main.rs
#![feature(proc_macro_hygiene)]
#![feature(decl_macro)]
#[macro_use]
extern crate rocket;
mod models;
mod routes;
// WebAPIURLroutes.rs
use routes::*;
fn main() {
rocket::ignite()
.mount("/", routes![index, todos, new_todo, todo_by_id])
.launch();
}
routes.rs
// JSON
use rocket_contrib::json::Json;
use crate::models::ToDo;
#[get("/")]
pub fn index() -> &'static str {
"Hello, world!"
}
/// TODO
/// JsonResponderimplJSON
#[get("/todos")]
pub fn todos() -> Json<Vec<ToDo>> {
Json(vec![ToDo {
id: 1,
title: "Read Rocket tutorial".into(),
description: "Read https://rocket.rs/guide/quickstart/".into(),
done: false,
}])
}
/// TODO
/// POST
#[post("/todos", data = "<todo>")]
pub fn new_todo(todo: Json<ToDo>) -> String {
format!("Accepted post request! {:?}", todo.0)
}
/// TODO
#[get("/todos/<todoid>")]
pub fn todo_by_id(todoid: u32) -> String {
let todo = ToDo {
id: 1,
title: "Read Rocket tutorial".into(),
description: "Read https://rocket.rs/guide/quickstart/".into(),
done: false,
};
format!("{:?}", todo)
}
models.rs
use serde::{Deserialize, Serialize};
/// TODOmodels.rs
#[derive(Debug, Serialize, Deserialize)]
pub struct ToDo {
pub id: u32,
pub title: String,
pub description: String,
pub done: bool,
}
$ cargo run
Configured for development.
=> address: localhost
=> port: 8000
=> log: normal
=> workers: 8
=> secret key: generated
=> limits: forms = 32KiB
=> tls: disabled
Mounting '/':
=> GET /
=> GET /todos
=> POST /todos
=> GET /todos/<todoid>
Rocket has launched from http://localhost:8000
curl
$ curl -i http://localhost:8000/todos
HTTP/1.1 200 OK
Content-Type: application/json
Server: Rocket
Content-Length: 111
Date: Wed, 04 Jul 2018 13:44:50 GMT
[{"id":1,"title":"Read Rocket tutorial","description":"Read https://rocket.rs/guide/quickstart/","done":false}]
OK,
POST
$ curl -i -H "Content-Type: application/json" -X POST -d '{"id": 100, "title":"Read this book", "description": "http://shop.oreilly.com/product/0636920040385.do", "done": false}' http://localhost:20000/todos
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Server: Rocket
Content-Length: 142
Date: Thu, 05 Jul 2018 03:55:22 GMT
Accepted post request! ToDo { id: 100, title: "Read this book", description: "http://shop.oreilly.com/product/0636920040385.do", done: false }
POSTOK
JsonJSONResponderRocketResponderimpl
RocketResponderimplimplResponderimpl
&'static str, &str, String | text/plain |
NamedFile | |
Redirect | URL |
Stream | HTTP |
Json | application/jsonJSON |
Template | Template |
rocket::response::status | Accepted203 Accepted |
Option | Some(T)TResponderNone404 Not Found |
Result<T,E> | Ok(T)TErr(E)UResponder |
3Wrapping ResponderWrapResponder
JSON
fn sample() -> Json<ToDo> {
Json(ToDo {
id: 1,
title: "Read Rocket tutorial".into(),
description: "Read https://rocket.rs/guide/quickstart/".into(),
done: false,
})
}
$ curl http://localhost:8000/todos
{"id":1,"title":"Read Rocket tutorial","description":"Read https://rocket.rs/guide/quickstart/","done":false}
Vector
fn sample() -> Vec<Json<ToDo>> {
Json(vec![ToDo {
id: 1,
title: "Read Rocket tutorial".into(),
description: "Read https://rocket.rs/guide/quickstart/".into(),
done: false,
}])
}
$ curl http://localhost:8000/todos
[{"id":1,"title":"Read Rocket tutorial","description":"Read https://rocket.rs/guide/quickstart/","done":false}]
JSONArray
use rocket::response::status::Accepted;
fn sample() -> Accepted<Vec<Json<ToDo>>> {
Accepted(Some(Json(vec![ToDo {
id: 1,
title: "Read Rocket tutorial".into(),
description: "Read https://rocket.rs/guide/quickstart/".into(),
done: false,
}])))
}
$ curl -i http://localhost:8000/todos
HTTP/1.1 202 Accepted
Content-Type: application/json
Server: Rocket
Content-Length: 111
Date: Fri, 06 Jul 2018 15:32:19 GMT
[{"id":1,"title":"Read Rocket tutorial","description":"Read https://rocket.rs/guide/quickstart/","done":false}]
Status code202 Accepted