mirror of
https://github.com/YGGverse/aquatic.git
synced 2026-03-31 17:55:36 +00:00
http_protocol: implement axum IntoResponse, use in http_private
This commit is contained in:
parent
5e79df8e7e
commit
98e7e5cc13
6 changed files with 70 additions and 41 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -171,6 +171,7 @@ name = "aquatic_http_protocol"
|
|||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"axum",
|
||||
"bendy",
|
||||
"criterion",
|
||||
"hex",
|
||||
|
|
|
|||
1
TODO.md
1
TODO.md
|
|
@ -11,7 +11,6 @@
|
|||
* site will likely want num_seeders and num_leechers for all torrents..
|
||||
|
||||
* aquatic_http_protocol
|
||||
* Implement axum IntoResponse behind feature gate
|
||||
* don't require compact=1?
|
||||
|
||||
## Medium priority
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ name = "aquatic_http_private"
|
|||
[dependencies]
|
||||
aquatic_cli_helpers = "0.2.0"
|
||||
aquatic_common = { version = "0.2.0", features = ["rustls-config"] }
|
||||
aquatic_http_protocol = "0.2.0"
|
||||
aquatic_http_protocol = { version = "0.2.0", features = ["with-axum"] }
|
||||
aquatic_toml_config = "0.2.0"
|
||||
|
||||
anyhow = "1"
|
||||
|
|
|
|||
|
|
@ -2,12 +2,10 @@ use aquatic_common::CanonicalSocketAddr;
|
|||
use axum::{
|
||||
extract::{ConnectInfo, Path, RawQuery},
|
||||
headers::UserAgent,
|
||||
http::StatusCode,
|
||||
response::IntoResponse,
|
||||
Extension, TypedHeader,
|
||||
};
|
||||
use sqlx::mysql::MySqlPool;
|
||||
use std::{borrow::Cow, net::SocketAddr, sync::Arc};
|
||||
use std::{net::SocketAddr, sync::Arc};
|
||||
|
||||
use aquatic_http_protocol::{
|
||||
request::AnnounceRequest,
|
||||
|
|
@ -29,11 +27,11 @@ pub async fn announce(
|
|||
opt_user_agent: Option<TypedHeader<UserAgent>>,
|
||||
Path(user_token): Path<String>,
|
||||
RawQuery(query): RawQuery,
|
||||
) -> Result<axum::response::Response, axum::response::Response> {
|
||||
let query = query.ok_or_else(|| create_failure_response("Empty query string"))?;
|
||||
) -> Result<Response, FailureResponse> {
|
||||
let query = query.ok_or_else(|| FailureResponse::new("Empty query string"))?;
|
||||
|
||||
let request = AnnounceRequest::from_query_string(&query)
|
||||
.map_err(|_| create_failure_response("Malformed request"))?;
|
||||
.map_err(|_| FailureResponse::new("Malformed request"))?;
|
||||
|
||||
let request_worker_index = RequestWorkerIndex::from_info_hash(&config, request.info_hash);
|
||||
let opt_user_agent = opt_user_agent.map(|header| header.as_str().to_owned());
|
||||
|
|
@ -42,8 +40,7 @@ pub async fn announce(
|
|||
|
||||
let (validated_request, opt_warning_message) =
|
||||
db::validate_announce_request(&pool, source_addr, opt_user_agent, user_token, request)
|
||||
.await
|
||||
.map_err(|r| create_response(Response::Failure(r)))?;
|
||||
.await?;
|
||||
|
||||
let response_receiver = request_sender
|
||||
.send_to(request_worker_index, validated_request, source_addr)
|
||||
|
|
@ -58,39 +55,11 @@ pub async fn announce(
|
|||
r.warning_message = opt_warning_message;
|
||||
}
|
||||
|
||||
Ok(create_response(response))
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
fn create_response(response: Response) -> axum::response::Response {
|
||||
let mut response_bytes = Vec::with_capacity(128);
|
||||
|
||||
response.write(&mut response_bytes).unwrap();
|
||||
|
||||
(
|
||||
StatusCode::OK,
|
||||
[("Content-type", "text/plain; charset=utf-8")],
|
||||
response_bytes,
|
||||
)
|
||||
.into_response()
|
||||
}
|
||||
|
||||
fn create_failure_response<R: Into<Cow<'static, str>>>(reason: R) -> axum::response::Response {
|
||||
let mut response_bytes = Vec::with_capacity(64);
|
||||
|
||||
FailureResponse::new(reason)
|
||||
.write(&mut response_bytes)
|
||||
.unwrap();
|
||||
|
||||
(
|
||||
StatusCode::OK,
|
||||
[("Content-type", "text/plain; charset=utf-8")],
|
||||
response_bytes,
|
||||
)
|
||||
.into_response()
|
||||
}
|
||||
|
||||
fn internal_error(error: String) -> axum::response::Response {
|
||||
fn internal_error(error: String) -> FailureResponse {
|
||||
::log::error!("{}", error);
|
||||
|
||||
create_failure_response("Internal error")
|
||||
FailureResponse::new("Internal error")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,8 +22,12 @@ name = "bench_announce_response_to_bytes"
|
|||
path = "benches/bench_announce_response_to_bytes.rs"
|
||||
harness = false
|
||||
|
||||
[features]
|
||||
with-axum = ["axum"]
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1"
|
||||
axum = { version = "0.5", optional = true, default-features = false }
|
||||
hex = { version = "0.4", default-features = false }
|
||||
httparse = "1"
|
||||
itoa = "1"
|
||||
|
|
|
|||
|
|
@ -112,6 +112,21 @@ impl AnnounceResponse {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "with-axum")]
|
||||
impl axum::response::IntoResponse for AnnounceResponse {
|
||||
fn into_response(self) -> axum::response::Response {
|
||||
let mut response_bytes = Vec::with_capacity(128);
|
||||
|
||||
self.write(&mut response_bytes).unwrap();
|
||||
|
||||
(
|
||||
[("Content-type", "text/plain; charset=utf-8")],
|
||||
response_bytes,
|
||||
)
|
||||
.into_response()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ScrapeResponse {
|
||||
/// BTreeMap instead of HashMap since keys need to be serialized in order
|
||||
|
|
@ -142,6 +157,21 @@ impl ScrapeResponse {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "with-axum")]
|
||||
impl axum::response::IntoResponse for ScrapeResponse {
|
||||
fn into_response(self) -> axum::response::Response {
|
||||
let mut response_bytes = Vec::with_capacity(128);
|
||||
|
||||
self.write(&mut response_bytes).unwrap();
|
||||
|
||||
(
|
||||
[("Content-type", "text/plain; charset=utf-8")],
|
||||
response_bytes,
|
||||
)
|
||||
.into_response()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct FailureResponse {
|
||||
#[serde(rename = "failure reason")]
|
||||
|
|
@ -170,6 +200,21 @@ impl FailureResponse {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "with-axum")]
|
||||
impl axum::response::IntoResponse for FailureResponse {
|
||||
fn into_response(self) -> axum::response::Response {
|
||||
let mut response_bytes = Vec::with_capacity(64);
|
||||
|
||||
self.write(&mut response_bytes).unwrap();
|
||||
|
||||
(
|
||||
[("Content-type", "text/plain; charset=utf-8")],
|
||||
response_bytes,
|
||||
)
|
||||
.into_response()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum Response {
|
||||
|
|
@ -191,6 +236,17 @@ impl Response {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "with-axum")]
|
||||
impl axum::response::IntoResponse for Response {
|
||||
fn into_response(self) -> axum::response::Response {
|
||||
match self {
|
||||
Self::Announce(r) => r.into_response(),
|
||||
Self::Scrape(r) => r.into_response(),
|
||||
Self::Failure(r) => r.into_response(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
impl quickcheck::Arbitrary for ResponsePeer<Ipv4Addr> {
|
||||
fn arbitrary(g: &mut quickcheck::Gen) -> Self {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue