handle-disconnect-fix-payload-format
This commit is contained in:
69
src/main.rs
69
src/main.rs
@@ -1,6 +1,7 @@
|
||||
use actix_web::{HttpRequest, web, App, HttpResponse, HttpServer, web::Bytes};
|
||||
use actix_web::middleware::Logger;
|
||||
use redis::{Client, AsyncCommands};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::env;
|
||||
use futures::StreamExt;
|
||||
@@ -8,27 +9,32 @@ use tokio::sync::broadcast;
|
||||
use actix_web::error::{ErrorUnauthorized, ErrorInternalServerError as ServerError};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use tokio::task::JoinHandle;
|
||||
|
||||
|
||||
async fn test_handler() -> Result<HttpResponse, actix_web::Error> {
|
||||
Ok(HttpResponse::Ok().body("Hello, World!"))
|
||||
}
|
||||
|
||||
|
||||
mod data;
|
||||
|
||||
|
||||
#[derive(Clone)]
|
||||
struct AppState {
|
||||
tasks: Arc<Mutex<HashMap<String, JoinHandle<()>>>>,
|
||||
redis: Client,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct RedisMessageData {
|
||||
payload: HashMap<String, String>,
|
||||
kind: String
|
||||
}
|
||||
|
||||
async fn connect_handler(
|
||||
req: HttpRequest,
|
||||
state: web::Data<AppState>,
|
||||
) -> Result<HttpResponse, actix_web::Error> {
|
||||
let token = match req.headers().get("Authorization") {
|
||||
Some(val) => val.to_str().unwrap_or(""),
|
||||
Some(val) => val.to_str()
|
||||
.unwrap_or("")
|
||||
.split(" ")
|
||||
.last()
|
||||
.unwrap_or(""),
|
||||
None => return Err(ErrorUnauthorized("Unauthorized")),
|
||||
};
|
||||
let listener_id = data::get_auth_id(&token).await.map_err(|e| {
|
||||
@@ -56,9 +62,9 @@ async fn connect_handler(
|
||||
let handle = tokio::spawn(async move {
|
||||
let conn = state_clone.redis.get_async_connection().await.unwrap();
|
||||
let mut pubsub = conn.into_pubsub();
|
||||
|
||||
pubsub.subscribe("new_follower").await.unwrap();
|
||||
println!("'new_follower' subscribed");
|
||||
let followers_channel = format!("new_follower:{}", listener_id);
|
||||
pubsub.subscribe(followers_channel.clone()).await.unwrap();
|
||||
println!("'{}' subscribed", followers_channel);
|
||||
pubsub.subscribe("new_shout").await.unwrap();
|
||||
println!("'new_shout' subscribed");
|
||||
pubsub.subscribe("new_reaction").await.unwrap();
|
||||
@@ -71,9 +77,17 @@ async fn connect_handler(
|
||||
}
|
||||
|
||||
while let Some(msg) = pubsub.on_message().next().await {
|
||||
let payload: HashMap<String, String> = msg.get_payload().unwrap();
|
||||
if data::is_fitting(listener_id, payload.clone()).await.is_ok() {
|
||||
let _ = tx.send(serde_json::to_string(&payload).unwrap());
|
||||
let message_str: String = msg.get_payload().unwrap();
|
||||
let message_data: RedisMessageData = serde_json::from_str(&message_str).unwrap();
|
||||
if data::is_fitting(listener_id, message_data.kind.to_string(), message_data.payload).await.is_ok() {
|
||||
let send_result = tx.send(message_str);
|
||||
if send_result.is_err() {
|
||||
let _ = con.srem::<&str, &i32, usize>("authors-online", &listener_id).await.map_err(|e| {
|
||||
eprintln!("Failed to remove author from online list: {}", e);
|
||||
ServerError("Internal Server Error")
|
||||
});
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
@@ -95,32 +109,6 @@ async fn connect_handler(
|
||||
}
|
||||
|
||||
|
||||
async fn disconnect_handler(
|
||||
req: HttpRequest,
|
||||
state: web::Data<AppState>,
|
||||
) -> Result<HttpResponse, actix_web::Error> {
|
||||
let token = match req.headers().get("Authorization") {
|
||||
Some(val) => val.to_str().unwrap_or(""),
|
||||
None => return Err(ErrorUnauthorized("Unauthorized")),
|
||||
};
|
||||
let listener_id = data::get_auth_id(&token).await.map_err(|e| {
|
||||
eprintln!("TOKEN check failed: {}", e);
|
||||
ErrorUnauthorized("Unauthorized")
|
||||
})?;
|
||||
if let Some(handle) = state.tasks.lock().unwrap().remove(&format!("{}", listener_id)) {
|
||||
handle.abort();
|
||||
let mut con = state.redis.get_async_connection().await.map_err(|e| {
|
||||
eprintln!("Failed to get async connection: {}", e);
|
||||
ServerError("Internal Server Error")
|
||||
})?;
|
||||
con.srem::<&str, &i32, usize>("authors-online", &listener_id).await.map_err(|e| {
|
||||
eprintln!("Failed to remove author from online list: {}", e);
|
||||
ServerError("Internal Server Error")
|
||||
})?;
|
||||
}
|
||||
Ok(HttpResponse::Ok().finish())
|
||||
}
|
||||
|
||||
#[actix_web::main]
|
||||
async fn main() -> std::io::Result<()> {
|
||||
let redis_url = env::var("REDIS_URL").unwrap_or_else(|_| String::from("redis://127.0.0.1/"));
|
||||
@@ -136,7 +124,6 @@ async fn main() -> std::io::Result<()> {
|
||||
.wrap(Logger::default())
|
||||
.app_data(web::Data::new(state.clone()))
|
||||
.route("/", web::get().to(connect_handler))
|
||||
.route("/test", web::post().to(test_handler))
|
||||
})
|
||||
.bind("0.0.0.0:8080")?
|
||||
.run()
|
||||
|
Reference in New Issue
Block a user