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
[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"] }
reqwest = { version = "0.11", features = ["json", "rustls-tls", "cookies", "gzip"], default-features = false }
serde_json = "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 rocket::{serde::{Deserialize, json::Json}, State, http::Status};
use rocket::http::Header;
use rocket::{Request, Response};
use rocket::fairing::{Fairing, Info, Kind};
use actix_web::{App, HttpResponse, HttpServer, Responder, get, post, web, middleware, http::header};
use actix_cors::Cors;
use serde_json::json;
use serde::Deserialize;
use std::sync::RwLock;
mod api;
use api::{APIClient, APIError, Format};
struct StateData {
client: APIClient
struct AppState {
client: RwLock<APIClient>
}
#[derive(Deserialize)]
@ -26,7 +23,7 @@ struct DeezerTrack {
}
#[get("/")]
fn index() -> &'static str {
async fn index() -> &'static str {
"marecchione gay af"
}
@ -36,32 +33,27 @@ struct RequestParams {
ids: Vec<u32>,
}
#[post("/get_url", format = "json", data = "<req>")]
async fn get_url(req: Json<RequestParams>, state_data: &State<RwLock<StateData>>) -> (Status, String) {
#[post("/get_url")]
async fn get_url(req: web::Json<RequestParams>, data: web::Data<AppState>) -> impl Responder {
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() {
return (Status::BadRequest, "ID list cannot be empty".to_string());
return HttpResponse::BadRequest().body("ID list cannot be empty");
}
let mut client: APIClient;
let old_license: String;
{
let state_data_read = state_data.read().unwrap();
old_license = state_data_read.client.license_token.clone();
client = state_data_read.client.clone();
}
let mut client = data.client.read().unwrap().clone();
let old_license = client.license_token.clone();
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;
match resp {
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() {
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();
@ -70,43 +62,46 @@ async fn get_url(req: Json<RequestParams>, state_data: &State<RwLock<StateData>>
let media_resp;
match media_result {
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 {
let mut state_data_write = state_data.write().unwrap();
state_data_write.client = client;
let mut client_write = data.client.write().unwrap();
*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")]
fn send_options() -> Status {
Status::Ok
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
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 {
Info {
name: "Add CORS headers to responses",
kind: Kind::Response
}
}
env_logger::init();
async fn on_response<'r>(&self, _request: &'r Request<'_>, response: &mut Response<'r>) {
response.set_header(Header::new("Access-Control-Allow-Origin", "*"));
response.set_header(Header::new("Access-Control-Allow-Headers", "*"));
}
}
HttpServer::new(move || {
let cors = Cors::default()
.allow_any_origin()
.allowed_methods(vec!["GET", "POST", "OPTIONS", "HEAD"])
.allowed_header(header::CONTENT_TYPE)
.max_age(3600);
#[launch]
fn rocket() -> _ {
rocket::build()
.manage(RwLock::new(StateData { client: APIClient::new() }))
.mount("/", routes![index, get_url, send_options])
.attach(CORS)
App::new()
.wrap(middleware::Logger::default())
.wrap(cors)
.wrap(middleware::Compress::default())
.app_data(client.clone())
.service(index)
.service(get_url)
})
.bind(format!("127.0.0.1:{}", port))?
.run()
.await
}