Initial axum port

This commit is contained in:
Timo Ley 2021-08-26 17:45:38 +02:00
parent 002faa9601
commit 2e608c7ece
4 changed files with 138 additions and 132 deletions

View file

@ -7,7 +7,10 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
actix-web = "3" tokio = { version = "1.0", features = ["full"] }
axum = "0.2.1"
tower = { version = "0.4", features = ["util", "timeout"] }
tower-http = { version = "0.1", features = ["add-extension", "trace"] }
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.51" serde_json = "1.0.51"
sqlx = { version = "0.3", features = [ "mysql" ] } sqlx = { version = "0.3", features = [ "mysql" ] }

View file

@ -1,21 +1,25 @@
use actix_web::{HttpServer, App};
use std::{io, env}; use std::{io, env};
use sqlx::MySqlPool; use sqlx::MySqlPool;
use std::net::SocketAddr;
use axum::Router;
use tower_http::add_extension::AddExtensionLayer;
mod v1; mod v1;
#[actix_web::main] #[tokio::main]
async fn main() -> io::Result<()>{ async fn main() {
let database_url = env::var("DBURL").unwrap(); let database_url = env::var("DBURL").unwrap();
let db_pool = MySqlPool::new(&database_url).await.unwrap(); let db_pool = MySqlPool::new(&database_url).await.unwrap();
let mut server = HttpServer::new(move || { let app = Router::new()
App::new() .nest("/v1", v1::routes())
.data(db_pool.clone()) .layer(AddExtensionLayer::new(db_pool));
.configure(v1::init)
});
server = server.bind(env::var("LISTEN").unwrap())?; let addr: SocketAddr = env::var("LISTEN").expect("The LISTEN env var ist not set").parse().expect("The LISTEN env var is set incorrectly");
server.run().await
axum::Server::bind(&addr)
.serve(app.into_make_service())
.await
.expect("Something went wrong :(");
} }

View file

@ -2,4 +2,4 @@ mod routes;
pub mod models; pub mod models;
mod sql; mod sql;
pub use routes::init; pub use routes::routes;

View file

@ -1,140 +1,139 @@
use actix_web::{web, get, Responder, HttpResponse};
use crate::v1::models::*; use crate::v1::models::*;
use sqlx::{MySqlPool, Error}; use sqlx::{MySqlPool, Error};
use axum::{Router, Json};
use axum::routing::BoxRoute;
use axum::response::IntoResponse;
use axum::handler::get;
use axum::extract::{Query, Extension};
use axum::http::StatusCode;
#[get("/v1/meme")] async fn meme(params: Query<MemeIDQuery>, Extension(db_pool): Extension<MySqlPool>) -> impl IntoResponse {
async fn meme(params: web::Query<MemeIDQuery>, db_pool: web::Data<MySqlPool>) -> impl Responder { let q = Meme::get(params.id, &db_pool).await;
let q = Meme::get(params.id, db_pool.get_ref()).await;
match q { match q {
Ok(meme) => HttpResponse::Ok().json(MemeResponse { Ok(meme) => (StatusCode::OK, Json(MemeResponse {
status: 200, status: 200,
error: None, error: None,
meme: Option::from(meme) meme: Some(meme)
}), })),
Err(err) => match err { Err(err) => match err {
Error::RowNotFound => HttpResponse::NotFound().json(MemeResponse { Error::RowNotFound => (StatusCode::NOT_FOUND, Json(MemeResponse {
status: 404,
error: Option::from(String::from("Meme not found")),
meme: None
}),
_ => HttpResponse::InternalServerError().json(MemeResponse {
status: 500,
error: Option::from(String::from("Internal Server Error")),
meme: None
})
}
}
}
#[get("/v1/memes")]
async fn memes(params: web::Query<MemeFilterQuery>, db_pool: web::Data<MySqlPool>) -> impl Responder {
let q = Meme::get_all(params.0, db_pool.get_ref()).await;
match q {
Ok(memes) => HttpResponse::Ok().json(MemesResponse {
status: 200,
error: None,
memes: Option::from(memes)
}),
_ => HttpResponse::InternalServerError().json(MemesResponse {
status: 500,
error: Option::from(String::from("Internal Server Error")),
memes: None
})
}
}
#[get("/v1/category")]
async fn category(params: web::Query<IDQuery>, db_pool: web::Data<MySqlPool>) -> impl Responder {
let q = Category::get(&params.id, db_pool.get_ref()).await;
match q {
Ok(category) => HttpResponse::Ok().json(CategoryResponse { status: 200, error: None, category: Option::from(category)}),
Err(err) => match err {
Error::RowNotFound => HttpResponse::NotFound().json(CategoryResponse {
status: 404,
error: Option::from(String::from("Category not found")),
category: None
}),
_ => HttpResponse::InternalServerError().json(CategoryResponse {
status: 500,
error: Option::from(String::from("Internal Server Error")),
category: None
})
}
}
}
#[get("/v1/categories")]
async fn categories(db_pool: web::Data<MySqlPool>) -> impl Responder {
let q = Category::get_all(db_pool.get_ref()).await;
match q {
Ok(categories) => HttpResponse::Ok().json(CategoriesResponse { status: 200, error: None, categories: Option::from(categories)}),
_ => HttpResponse::InternalServerError().json(CategoriesResponse {
status: 500,
error: Option::from(String::from("Internal Server Error")),
categories: None
})
}
}
#[get("/v1/user")]
async fn user(params: web::Query<UserIDQuery>, db_pool: web::Data<MySqlPool>) -> impl Responder {
let q = User::get(params.0,db_pool.get_ref()).await;
match q {
Ok(user) => HttpResponse::Ok().json(UserResponse { status: 200, error: None, user: Option::from(user)}),
_ => HttpResponse::InternalServerError().json(UserResponse {
status: 500,
error: Option::from(String::from("Internal Server Error")),
user: None
})
}
}
#[get("/v1/users")]
async fn users(db_pool: web::Data<MySqlPool>) -> impl Responder {
let q = User::get_all(db_pool.get_ref()).await;
match q {
Ok(users) => HttpResponse::Ok().json(UsersResponse { status: 200, error: None, users: Option::from(users)}),
_ => HttpResponse::InternalServerError().json(UsersResponse {
status: 500,
error: Option::from(String::from("Internal Server Error")),
users: None
})
}
}
#[get("/v1/random")]
async fn random(params: web::Query<MemeFilterQuery>, db_pool: web::Data<MySqlPool>) -> impl Responder {
let q = Meme::get_random(params.0, db_pool.get_ref()).await;
match q {
Ok(random) => HttpResponse::Ok().json(MemeResponse {
status: 200,
error: None,
meme: Some(random)
}),
Err(err) => match err {
Error::RowNotFound => HttpResponse::NotFound().json(MemeResponse {
status: 404, status: 404,
error: Some(String::from("Meme not found")), error: Some(String::from("Meme not found")),
meme: None meme: None
}), })),
_ => HttpResponse::InternalServerError().json(MemeResponse { _ => (StatusCode::INTERNAL_SERVER_ERROR, Json(MemeResponse {
status: 500, status: 500,
error: Some(String::from("Internal Server Error")), error: Some(String::from("Internal Server Error")),
meme: None meme: None
}) }))
}
}
}
async fn memes(params: Query<MemeFilterQuery>, Extension(db_pool): Extension<MySqlPool>) -> impl IntoResponse {
let q = Meme::get_all(params.0, &db_pool).await;
match q {
Ok(memes) => (StatusCode::OK, Json(MemesResponse {
status: 200,
error: None,
memes: Some(memes)
})),
_ => (StatusCode::INTERNAL_SERVER_ERROR, Json(MemesResponse {
status: 500,
error: Some(String::from("Internal Server Error")),
memes: None
}))
}
}
async fn category(params: Query<IDQuery>, Extension(db_pool): Extension<MySqlPool>) -> impl IntoResponse {
let q = Category::get(&params.id, &db_pool).await;
match q {
Ok(category) => (StatusCode::OK, Json(CategoryResponse { status: 200, error: None, category: Some(category)})),
Err(err) => match err {
Error::RowNotFound => (StatusCode::NOT_FOUND, Json(CategoryResponse {
status: 404,
error: Some(String::from("Category not found")),
category: None
})),
_ => (StatusCode::INTERNAL_SERVER_ERROR, Json(CategoryResponse {
status: 500,
error: Some(String::from("Internal Server Error")),
category: None
}))
}
}
}
async fn categories(Extension(db_pool): Extension<MySqlPool>) -> impl IntoResponse {
let q = Category::get_all(&db_pool).await;
match q {
Ok(categories) => (StatusCode::OK, Json(CategoriesResponse { status: 200, error: None, categories: Some(categories)})),
_ => (StatusCode::INTERNAL_SERVER_ERROR, Json(CategoriesResponse {
status: 500,
error: Some(String::from("Internal Server Error")),
categories: None
}))
}
}
async fn user(params: Query<UserIDQuery>, Extension(db_pool): Extension<MySqlPool>) -> impl IntoResponse {
let q = User::get(params.0, &db_pool).await;
match q {
Ok(user) => (StatusCode::OK, Json(UserResponse { status: 200, error: None, user: Some(user)})),
_ => (StatusCode::INTERNAL_SERVER_ERROR, Json(UserResponse {
status: 500,
error: Some(String::from("Internal Server Error")),
user: None
}))
}
}
async fn users(Extension(db_pool): Extension<MySqlPool>) -> impl IntoResponse {
let q = User::get_all(&db_pool).await;
match q {
Ok(users) => (StatusCode::OK, Json(UsersResponse { status: 200, error: None, users: Some(users)})),
_ => (StatusCode::INTERNAL_SERVER_ERROR, Json(UsersResponse {
status: 500,
error: Some(String::from("Internal Server Error")),
users: None
}))
}
}
async fn random(params: Query<MemeFilterQuery>, Extension(db_pool): Extension<MySqlPool>) -> impl IntoResponse {
let q = Meme::get_random(params.0, &db_pool).await;
match q {
Ok(random) => (StatusCode::OK, Json(MemeResponse {
status: 200,
error: None,
meme: Some(random)
})),
Err(err) => match err {
Error::RowNotFound => (StatusCode::NOT_FOUND, Json(MemeResponse {
status: 404,
error: Some(String::from("Meme not found")),
meme: None
})),
_ => (StatusCode::INTERNAL_SERVER_ERROR, Json(MemeResponse {
status: 500,
error: Some(String::from("Internal Server Error")),
meme: None
}))
} }
} }
} }
//TODO: Implement random meme endpoint
//TODO: Implement upload endpoint //TODO: Implement upload endpoint
pub fn init(cfg: &mut web::ServiceConfig) { pub fn routes() -> Router<BoxRoute> {
cfg.service(meme); Router::new()
cfg.service(memes); .route("/meme", get(meme))
cfg.service(category); .route("/memes", get(memes))
cfg.service(categories); .route("/category", get(category))
cfg.service(user); .route("/categories", get(categories))
cfg.service(users); .route("/user", get(user))
cfg.service(random); .route("/users", get(users))
.route("/random", get(random))
.boxed()
} }