Skip to content

Commit bc9f676

Browse files
committed
refactor: return 400 if json is not valid
1 parent 6142f1f commit bc9f676

File tree

6 files changed

+46
-39
lines changed

6 files changed

+46
-39
lines changed

src/webhook/actix_web.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
use crate::Incoming;
22
use actix_web::{
33
dev::Payload,
4-
error::{Error, ErrorUnauthorized},
4+
error::{Error, ErrorBadRequest, ErrorUnauthorized},
55
web::Json,
66
FromRequest, HttpRequest,
77
};
8+
use serde::de::DeserializeOwned;
89
use std::{
910
future::Future,
1011
pin::Pin,
1112
task::{ready, Context, Poll},
1213
};
13-
use serde::de::DeserializeOwned;
1414

1515
#[doc(hidden)]
1616
pub struct IncomingFut<T: DeserializeOwned> {
@@ -36,9 +36,11 @@ where
3636
}));
3737
}
3838
}
39+
40+
return Poll::Ready(Err(ErrorUnauthorized("401")));
3941
}
4042

41-
Poll::Ready(Err(ErrorUnauthorized("401")))
43+
Poll::Ready(Err(ErrorBadRequest("400")))
4244
}
4345
}
4446

src/webhook/axum.rs

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -35,31 +35,31 @@ impl<T> Clone for WebhookState<T> {
3535
/// use topgg::{Vote, Webhook};
3636
/// use tokio::net::TcpListener;
3737
/// use std::sync::Arc;
38-
///
38+
///
3939
/// struct MyVoteListener {}
40-
///
40+
///
4141
/// #[async_trait::async_trait]
4242
/// impl Webhook<Vote> for MyVoteListener {
4343
/// async fn callback(&self, vote: Vote) {
4444
/// println!("A user with the ID of {} has voted us on Top.gg!", vote.voter_id);
4545
/// }
4646
/// }
47-
///
47+
///
4848
/// async fn index() -> &'static str {
4949
/// "Hello, World!"
5050
/// }
51-
///
51+
///
5252
/// #[tokio::main]
5353
/// async fn main() {
5454
/// let state = Arc::new(MyVoteListener {});
55-
///
55+
///
5656
/// let router = Router::new().route("/", get(index)).nest(
5757
/// "/votes",
5858
/// topgg::axum::webhook(env!("MY_TOPGG_WEBHOOK_SECRET").to_string(), Arc::clone(&state)),
5959
/// );
60-
///
60+
///
6161
/// let listener = TcpListener::bind("127.0.0.1:8080").await.unwrap();
62-
///
62+
///
6363
/// axum::serve(listener, router).await.unwrap();
6464
/// }
6565
/// ```
@@ -71,21 +71,26 @@ where
7171
T: Webhook<D>,
7272
{
7373
Router::new()
74-
.route("/", post(async |headers: HeaderMap, State(webhook): State<WebhookState<T>>, body: String| {
75-
if let Some(authorization) = headers.get("Authorization") {
76-
if let Ok(authorization) = authorization.to_str() {
77-
if authorization == *(webhook.password) {
78-
if let Ok(data) = serde_json::from_str(&body) {
79-
webhook.state.callback(data).await;
80-
81-
return (StatusCode::NO_CONTENT, ()).into_response();
74+
.route(
75+
"/",
76+
post(
77+
async |headers: HeaderMap, State(webhook): State<WebhookState<T>>, body: String| {
78+
if let Some(authorization) = headers.get("Authorization") {
79+
if let Ok(authorization) = authorization.to_str() {
80+
if authorization == *(webhook.password) {
81+
if let Ok(data) = serde_json::from_str(&body) {
82+
webhook.state.callback(data).await;
83+
84+
return (StatusCode::NO_CONTENT, ()).into_response();
85+
}
86+
}
8287
}
8388
}
84-
}
85-
}
86-
87-
(StatusCode::UNAUTHORIZED, ()).into_response()
88-
}))
89+
90+
(StatusCode::UNAUTHORIZED, ()).into_response()
91+
},
92+
),
93+
)
8994
.with_state(WebhookState {
9095
state,
9196
password: Arc::new(password),

src/webhook/mod.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ cfg_if::cfg_if! {
4646
}
4747
}
4848
}
49-
49+
5050
impl<T> Clone for Incoming<T>
5151
where
5252
T: Clone,
@@ -62,7 +62,6 @@ cfg_if::cfg_if! {
6262
}
6363
}
6464

65-
6665
cfg_if::cfg_if! {
6766
if #[cfg(any(feature = "axum", feature = "warp"))] {
6867
/// Webhook event handler.
@@ -72,4 +71,4 @@ cfg_if::cfg_if! {
7271
async fn callback(&self, data: T);
7372
}
7473
}
75-
}
74+
}

src/webhook/rocket.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,13 @@ where
1919
let headers = request.headers();
2020

2121
if let Some(authorization) = headers.get_one("Authorization") {
22-
if let Outcome::Success(data) = <Json<T> as FromData>::from_data(request, data).await {
23-
return Outcome::Success(Self {
22+
return match <Json<T> as FromData>::from_data(request, data).await {
23+
Outcome::Success(data) => Outcome::Success(Self {
2424
authorization: authorization.to_owned(),
2525
data: data.into_inner(),
26-
});
27-
}
26+
}),
27+
_ => Outcome::Error((Status::BadRequest, ())),
28+
};
2829
}
2930

3031
Outcome::Error((Status::Unauthorized, ()))

src/webhook/vote.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,4 @@ pub struct Vote {
6464
/// Query strings found on the vote page.
6565
#[serde(default, deserialize_with = "deserialize_query_string")]
6666
pub query: HashMap<String, String>,
67-
}
67+
}

src/webhook/warp.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use super::Webhook;
2-
use std::sync::Arc;
32
use serde::de::DeserializeOwned;
3+
use std::sync::Arc;
44
use warp::{body, header, http::StatusCode, path, Filter, Rejection, Reply};
55

66
/// Creates a new `warp` [`Filter`] for receiving webhook events.
@@ -13,31 +13,31 @@ use warp::{body, header, http::StatusCode, path, Filter, Rejection, Reply};
1313
/// use std::{net::SocketAddr, sync::Arc};
1414
/// use topgg::{Vote, Webhook};
1515
/// use warp::Filter;
16-
///
16+
///
1717
/// struct MyVoteListener {}
18-
///
18+
///
1919
/// #[async_trait::async_trait]
2020
/// impl Webhook<Vote> for MyVoteListener {
2121
/// async fn callback(&self, vote: Vote) {
2222
/// println!("A user with the ID of {} has voted us on Top.gg!", vote.voter_id);
2323
/// }
2424
/// }
25-
///
25+
///
2626
/// #[tokio::main]
2727
/// async fn main() {
2828
/// let state = Arc::new(MyVoteListener {});
29-
///
29+
///
3030
/// // POST /votes
3131
/// let webhook = topgg::warp::webhook(
3232
/// "votes",
3333
/// env!("MY_TOPGG_WEBHOOK_SECRET").to_string(),
3434
/// Arc::clone(&state),
3535
/// );
36-
///
36+
///
3737
/// let routes = warp::get().map(|| "Hello, World!").or(webhook);
38-
///
38+
///
3939
/// let addr: SocketAddr = "127.0.0.1:8080".parse().unwrap();
40-
///
40+
///
4141
/// warp::serve(routes).run(addr).await
4242
/// }
4343
/// ```

0 commit comments

Comments
 (0)