axum-restful
A restful framework based on axum
and sea-orm
with full features. Inspired by django-rest-framework
.
The goal of the project is to build an enterprise-level production framework with full features and modularity.
Features
- a Trait for the
struct
generated bysea-orm
to provide with GET, PATCH, PUT, DELETE methods tls
supportprometheus
metrics and metrics servergraceful shutdown
support
Quick start
A full example is exists at axum-restful/examples/demo
.
First, you can create a new crate like cargo new axum-restful-demo
.
Build a database service
You should have a database service before. It is recommended to use postgresql
database.
you can use docker and docker compose to start a postgresql
create a compose.yaml
in the same directory as Cargo.toml
services:
postgres:
image: postgres:15-bullseye
container_name: demo-postgres
restart: always
volumes:
- demo-postgres:/var/lib/postgresql/data
ports:
- "127.0.0.1:5432:5432"
environment:
- POSTGRES_DB=${POSTGRES_DB}
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
volumes:
demo-postgres:
a .env
file like
# config the base pg connect params
POSTGRES_DB=demo
POSTGRES_USER=demo-user
POSTGRES_PASSWORD=demo-password
# used by axum-restful framework to specific a database connection
DATABASE_URL=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@localhost:5432/${POSTGRES_DB}
finally, you can build a service with docker compose up -d
Write and migrate a migration
For more details, please refer to the sea-orm
documentation.
Install the sea-orm-cli
with cargo
$ cargo install sea-orm-cli
Configure dependencies and workspace in Cargo.toml
[]
= [".", "migration"]
[]
= "0.2"
= "0.6"
= { = "= 0.11.1", = ["sqlx-postgres", "runtime-tokio-rustls",]}
= { = "0.11", = ["macros", "sqlx-postgres", "runtime-tokio-rustls"] }
= "1.0"
= { = "1.0", = ["derive"] }
= { = "1", = ["full"]}
= "0.3"
= "0.1"
Setup the migration directory in ./migration
$ sea-orm-cli migrate init
project structure changed into
├── Cargo.lock
├── Cargo.toml
├── compose.yaml
├── migration
│ ├── Cargo.toml
│ ├── README.md
│ └── src
│ ├── lib.rs
│ ├── m20220101_000001_create_table.rs
│ └── main.rs
└── src
└── main.rs
edit the m20****_******_create_table.rs
file blow ./migration/src
use *;
;
/// Learn more at https://docs.rs/sea-query#iden
edit migration/Cargo.toml
to add dependencies
[]
...
= "0.2"
edit migration/src/main.rs
to specific a database connection an migrate
use *;
async
migrate the migration files
$ cd migration
$ cargo run
finally, you can see two tables named sql_migrations
and student
generated.
Generate entities
at the project root path
$ sea-orm-cli generate entity -o src/entities
will generate entities configure and code, now project structure changed into
├── Cargo.lock
├── Cargo.toml
├── compose.yaml
├── migration
│ ├── Cargo.toml
│ ├── README.md
│ └── src
│ ├── lib.rs
│ ├── m20220101_000001_create_table.rs
│ └── main.rs
└── src
├── entities
│ ├── mod.rs
│ ├── prelude.rs
│ └── student.rs
└── main.rs
edit the src/entities/student.rs
to add derive Default, Serialize, Deserialize
, add default value to id
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.0
use *;
use ;
edit src/main.rs
use Router;
use ModelView;
use student;
async
StudentView impl the ModelView<T>
, the T
is student::ActiveModel
that represent the student table configure
in the database, if will has full HTTP methods with GET, POST, PUT, PATCH, DELETE.
you can see the server is listen at port 3000
Verify the service
you can use curl
or httpie
to verify the service
check the https://httpie.io/docs/cli/installation
to install httpie
, if you have python3
, you can execute sudo python3 -m pip install httpie
POST
use curl
$ curl -H "Content-Type: application/json" -d '{"name": "student-1", "region": "south-1", "age": 11}' -X POST http://127.0.0.1:3000/api/student
use httpie
$ echo -n '{"name": "student-1", "region": "south-1", "age": 11}' | http POST http://127.0.0.1:3000/api/student
HTTP/1.1 201 Created
content-length: 0
date: Sat, 01 Apr 2023 02:50:41 GMT
GET list
$ http GET http://127.0.0.1:3000/api/student
HTTP/1.1 200 OK
content-length: 57
content-type: application/json
date: Sat, 01 Apr 2023 02:51:41 GMT
[
{
"age": 11,
"id": 1,
"name": "student-1",
"region": "south-1"
}
]
GET detail
$ http GET http://127.0.0.1:3000/api/student/1
HTTP/1.1 200 OK
content-length: 55
content-type: application/json
date: Sat, 01 Apr 2023 02:52:41 GMT
{
"age": 11,
"id": 1,
"name": "student-1",
"region": "south-1"
}
PUT detail
$ echo -n '{"name": "student-put-1", "region": "south-put-1", "age": 12, "id": 1}' | http PUT http://127.0.0.1:3000/api/student/1
HTTP/1.1 200 OK
content-length: 0
date: Sat, 01 Apr 2023 02:54:10 GMT
# and you can get again to verify put result
$ http GET http://127.0.0.1:3000/api/student
HTTP/1.1 200 OK
content-length: 65
content-type: application/json
date: Sat, 01 Apr 2023 02:54:59 GMT
[
{
"age": 12,
"id": 1,
"name": "student-put-1",
"region": "south-put-1"
}
]
PATCH detail
$ echo -n '{"name": "patch-name"}' | http PATCH http://127.0.0.1:3000/api/student/1
HTTP/1.1 200 OK
content-length: 0
date: Sat, 01 Apr 2023 02:57:46 GMT
# you can get again to verify the patch
$ http GET http://127.0.0.1:3000/api/student
HTTP/1.1 200 OK
content-length: 62
content-type: application/json
date: Sat, 01 Apr 2023 02:58:03 GMT
[
{
"age": 12,
"id": 1,
"name": "patch-name",
"region": "south-put-1"
}
]
DELETE detail
$ http DELETE http://127.0.0.1:3000/api/student/1
HTTP/1.1 204 No Content
date: Sat, 01 Apr 2023 02:59:16 GMT
# you can query again to verify
$ http GET http://127.0.0.1:3000/api/student
HTTP/1.1 200 OK
content-length: 2
content-type: application/json
date: Sat, 01 Apr 2023 02:59:43 GMT
[]
License
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.