switched framework to actix-web

This commit is contained in:
uh wot 2021-10-24 15:29:29 +02:00
parent 89a9303321
commit d2a7090033
Signed by: uhwot
GPG Key ID: CB2454984587B781
4 changed files with 549 additions and 489 deletions

935
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -6,9 +6,11 @@ edition = "2021"
# 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]
rocket = { version = "0.5.0-rc.1", features = ["json"], default-features = false } # using beta due to this: https://github.com/actix/actix-web/issues/2155
actix-web = "4.0.0-beta.10"
actix-cors = "0.6.0-beta.3"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
reqwest = { version = "0.11", features = ["json", "rustls-tls", "cookies", "gzip"], default-features = false } reqwest = { version = "0.11", features = ["json", "rustls-tls", "cookies", "gzip"], default-features = false }
serde_json = "1.0" serde_json = "1.0"
thiserror = "1.0" thiserror = "1.0"
regex = "1" env_logger = "0.9"

View File

@ -1 +1 @@
web: ROCKET_ADDRESS=0.0.0.0 ROCKET_PORT=$PORT ROCKET_KEEP_ALIVE=0 ./target/release/dzmedia web: ./target/release/dzmedia

View File

@ -1,17 +1,14 @@
#[macro_use] extern crate rocket; use actix_web::{App, HttpResponse, HttpServer, Responder, get, post, web, middleware, http::header};
use actix_cors::Cors;
use rocket::{serde::{Deserialize, json::Json}, State, http::Status};
use rocket::http::Header;
use rocket::{Request, Response};
use rocket::fairing::{Fairing, Info, Kind};
use serde_json::json; use serde_json::json;
use serde::Deserialize;
use std::sync::RwLock; use std::sync::RwLock;
mod api; mod api;
use api::{APIClient, APIError, Format}; use api::{APIClient, APIError, Format};
struct StateData { struct AppState {
client: APIClient client: RwLock<APIClient>
} }
#[derive(Deserialize)] #[derive(Deserialize)]
@ -26,7 +23,7 @@ struct DeezerTrack {
} }
#[get("/")] #[get("/")]
fn index() -> &'static str { async fn index() -> &'static str {
"marecchione gay af" "marecchione gay af"
} }
@ -36,32 +33,27 @@ struct RequestParams {
ids: Vec<u32>, ids: Vec<u32>,
} }
#[post("/get_url", format = "json", data = "<req>")] #[post("/get_url")]
async fn get_url(req: Json<RequestParams>, state_data: &State<RwLock<StateData>>) -> (Status, String) { async fn get_url(req: web::Json<RequestParams>, data: web::Data<AppState>) -> impl Responder {
if req.formats.is_empty() { if req.formats.is_empty() {
return (Status::BadRequest, "Format list cannot be empty".to_string()); return HttpResponse::BadRequest().body("Format list cannot be empty");
} }
if req.ids.is_empty() { if req.ids.is_empty() {
return (Status::BadRequest, "ID list cannot be empty".to_string()); return HttpResponse::BadRequest().body("ID list cannot be empty");
} }
let mut client: APIClient; let mut client = data.client.read().unwrap().clone();
let old_license: String; let old_license = client.license_token.clone();
{
let state_data_read = state_data.read().unwrap();
old_license = state_data_read.client.license_token.clone();
client = state_data_read.client.clone();
}
let resp: Result<DeezerTrackList, APIError> = client.api_call("song.getListData", &json!({"sng_ids":req.ids,"array_default":["SNG_ID","TRACK_TOKEN"]})).await; let resp: Result<DeezerTrackList, APIError> = client.api_call("song.getListData", &json!({"sng_ids":req.ids,"array_default":["SNG_ID","TRACK_TOKEN"]})).await;
let track_list; let track_list;
match resp { match resp {
Ok(t) => track_list = t, Ok(t) => track_list = t,
Err(e) => return (Status::InternalServerError, e.to_string()), Err(e) => return HttpResponse::InternalServerError().body(e.to_string()),
}; };
if track_list.data.is_empty() { if track_list.data.is_empty() {
return (Status::BadRequest, "No valid IDs found".to_string()) return HttpResponse::BadRequest().body("No valid IDs found");
} }
let track_tokens: Vec<&str> = track_list.data.iter().map(|t| t.TRACK_TOKEN.as_str()).collect(); let track_tokens: Vec<&str> = track_list.data.iter().map(|t| t.TRACK_TOKEN.as_str()).collect();
@ -70,43 +62,46 @@ async fn get_url(req: Json<RequestParams>, state_data: &State<RwLock<StateData>>
let media_resp; let media_resp;
match media_result { match media_result {
Ok(r) => media_resp = r, Ok(r) => media_resp = r,
Err(_) => return (Status::InternalServerError, "Error while getting response from media.deezer.com".to_string()) Err(_) => return HttpResponse::InternalServerError().body("Error while getting response from media.deezer.com"),
}; };
if client.license_token != old_license { if client.license_token != old_license {
let mut state_data_write = state_data.write().unwrap(); let mut client_write = data.client.write().unwrap();
state_data_write.client = client; *client_write = client;
} }
(Status::Ok, media_resp.text().await.unwrap()) HttpResponse::Ok()
.content_type("application/json")
.body(media_resp.text().await.unwrap())
} }
#[options("/get_url")] #[actix_web::main]
fn send_options() -> Status { async fn main() -> std::io::Result<()> {
Status::Ok let port = std::env::var("PORT").unwrap_or("8000".to_string());
} let port: u16 = port.parse().unwrap_or(8000);
pub struct CORS; let client = web::Data::new(AppState {
client: RwLock::new(APIClient::new()),
#[rocket::async_trait] });
impl Fairing for CORS {
fn info(&self) -> Info { env_logger::init();
Info {
name: "Add CORS headers to responses", HttpServer::new(move || {
kind: Kind::Response let cors = Cors::default()
} .allow_any_origin()
} .allowed_methods(vec!["GET", "POST", "OPTIONS", "HEAD"])
.allowed_header(header::CONTENT_TYPE)
async fn on_response<'r>(&self, _request: &'r Request<'_>, response: &mut Response<'r>) { .max_age(3600);
response.set_header(Header::new("Access-Control-Allow-Origin", "*"));
response.set_header(Header::new("Access-Control-Allow-Headers", "*")); App::new()
} .wrap(middleware::Logger::default())
} .wrap(cors)
.wrap(middleware::Compress::default())
#[launch] .app_data(client.clone())
fn rocket() -> _ { .service(index)
rocket::build() .service(get_url)
.manage(RwLock::new(StateData { client: APIClient::new() })) })
.mount("/", routes![index, get_url, send_options]) .bind(format!("127.0.0.1:{}", port))?
.attach(CORS) .run()
.await
} }