mirror of
https://github.com/tokio-rs/axum.git
synced 2024-11-21 22:56:46 +01:00
Add MongoDB example (#2535)
This commit is contained in:
parent
e784977aa6
commit
4d9017af7e
2 changed files with 145 additions and 0 deletions
14
examples/mongodb/Cargo.toml
Normal file
14
examples/mongodb/Cargo.toml
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
[package]
|
||||||
|
name = "example-mongodb"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
publish = false
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
axum = { path = "../../axum" }
|
||||||
|
mongodb = "2.8.0"
|
||||||
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
tokio = { version = "1.0", features = ["full"] }
|
||||||
|
tower-http = { version = "0.5.0", features = ["add-extension", "trace"] }
|
||||||
|
tracing = "0.1"
|
||||||
|
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
131
examples/mongodb/src/main.rs
Normal file
131
examples/mongodb/src/main.rs
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
//! Run with
|
||||||
|
//!
|
||||||
|
//! ```not_rust
|
||||||
|
//! cargo run -p example-mongodb
|
||||||
|
//! ```
|
||||||
|
|
||||||
|
use axum::{
|
||||||
|
extract::{Path, State},
|
||||||
|
http::StatusCode,
|
||||||
|
routing::{delete, get, post, put},
|
||||||
|
Json, Router,
|
||||||
|
};
|
||||||
|
use mongodb::{
|
||||||
|
bson::doc,
|
||||||
|
results::{DeleteResult, InsertOneResult, UpdateResult},
|
||||||
|
Client, Collection,
|
||||||
|
};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use tower_http::trace::TraceLayer;
|
||||||
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() {
|
||||||
|
// connecting to mongodb
|
||||||
|
let db_connection_str = std::env::var("DATABASE_URL").unwrap_or_else(|_| {
|
||||||
|
"mongodb://admin:password@127.0.0.1:27017/?authSource=admin".to_string()
|
||||||
|
});
|
||||||
|
let client = Client::with_uri_str(db_connection_str).await.unwrap();
|
||||||
|
|
||||||
|
// pinging the database
|
||||||
|
client
|
||||||
|
.database("axum-mongo")
|
||||||
|
.run_command(doc! { "ping": 1 }, None)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
println!("Pinged your database. Successfully connected to MongoDB!");
|
||||||
|
|
||||||
|
// logging middleware
|
||||||
|
tracing_subscriber::registry()
|
||||||
|
.with(
|
||||||
|
tracing_subscriber::EnvFilter::try_from_default_env()
|
||||||
|
.unwrap_or_else(|_| "example_mongo=debug,tower_http=debug".into()),
|
||||||
|
)
|
||||||
|
.with(tracing_subscriber::fmt::layer())
|
||||||
|
.init();
|
||||||
|
|
||||||
|
// run it
|
||||||
|
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
tracing::debug!("Listening on {}", listener.local_addr().unwrap());
|
||||||
|
axum::serve(listener, app(client)).await.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
// defining routes and state
|
||||||
|
fn app(client: Client) -> Router {
|
||||||
|
let collection: Collection<Member> = client.database("axum-mongo").collection("members");
|
||||||
|
|
||||||
|
Router::new()
|
||||||
|
.route("/create", post(create_member))
|
||||||
|
.route("/read/:id", get(read_member))
|
||||||
|
.route("/update", put(update_member))
|
||||||
|
.route("/delete/:id", delete(delete_member))
|
||||||
|
.layer(TraceLayer::new_for_http())
|
||||||
|
.with_state(collection)
|
||||||
|
}
|
||||||
|
|
||||||
|
// handler to create a new member
|
||||||
|
async fn create_member(
|
||||||
|
State(db): State<Collection<Member>>,
|
||||||
|
Json(input): Json<Member>,
|
||||||
|
) -> Result<Json<InsertOneResult>, (StatusCode, String)> {
|
||||||
|
let result = db.insert_one(input, None).await.map_err(internal_error)?;
|
||||||
|
|
||||||
|
Ok(Json(result))
|
||||||
|
}
|
||||||
|
|
||||||
|
// handler to read an existing member
|
||||||
|
async fn read_member(
|
||||||
|
State(db): State<Collection<Member>>,
|
||||||
|
Path(id): Path<u32>,
|
||||||
|
) -> Result<Json<Option<Member>>, (StatusCode, String)> {
|
||||||
|
let result = db
|
||||||
|
.find_one(doc! { "_id": id }, None)
|
||||||
|
.await
|
||||||
|
.map_err(internal_error)?;
|
||||||
|
|
||||||
|
Ok(Json(result))
|
||||||
|
}
|
||||||
|
|
||||||
|
// handler to update an existing member
|
||||||
|
async fn update_member(
|
||||||
|
State(db): State<Collection<Member>>,
|
||||||
|
Json(input): Json<Member>,
|
||||||
|
) -> Result<Json<UpdateResult>, (StatusCode, String)> {
|
||||||
|
let result = db
|
||||||
|
.replace_one(doc! { "_id": input.id }, input, None)
|
||||||
|
.await
|
||||||
|
.map_err(internal_error)?;
|
||||||
|
|
||||||
|
Ok(Json(result))
|
||||||
|
}
|
||||||
|
|
||||||
|
// handler to delete an existing member
|
||||||
|
async fn delete_member(
|
||||||
|
State(db): State<Collection<Member>>,
|
||||||
|
Path(id): Path<u32>,
|
||||||
|
) -> Result<Json<DeleteResult>, (StatusCode, String)> {
|
||||||
|
let result = db
|
||||||
|
.delete_one(doc! { "_id": id }, None)
|
||||||
|
.await
|
||||||
|
.map_err(internal_error)?;
|
||||||
|
|
||||||
|
Ok(Json(result))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn internal_error<E>(err: E) -> (StatusCode, String)
|
||||||
|
where
|
||||||
|
E: std::error::Error,
|
||||||
|
{
|
||||||
|
(StatusCode::INTERNAL_SERVER_ERROR, err.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
// defining Member type
|
||||||
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
struct Member {
|
||||||
|
#[serde(rename = "_id")]
|
||||||
|
id: u32,
|
||||||
|
name: String,
|
||||||
|
active: bool,
|
||||||
|
}
|
Loading…
Reference in a new issue