This commit is contained in:
Astro 2024-03-27 21:39:40 +01:00
parent 242a4f41cb
commit 9fc0e0cd57
7 changed files with 27 additions and 33 deletions

View file

@ -126,11 +126,11 @@ impl Actor {
id: self.uri(), id: self.uri(),
name: Some(match &self.kind { name: Some(match &self.kind {
ActorKind::TagRelay(tag) => ActorKind::TagRelay(tag) =>
format!("#{}", tag), format!("#{tag}"),
ActorKind::InstanceRelay(instance) => ActorKind::InstanceRelay(instance) =>
instance.to_string(), instance.to_string(),
ActorKind::LanguageRelay(language) => ActorKind::LanguageRelay(language) =>
format!("in {}", language), format!("in {language}"),
}), }),
icon: Some(activitypub::Media { icon: Some(activitypub::Media {
media_type: Some("Image".to_string()), media_type: Some("Image".to_string()),
@ -149,11 +149,11 @@ impl Actor {
}, },
preferred_username: Some(match &self.kind { preferred_username: Some(match &self.kind {
ActorKind::TagRelay(tag) => ActorKind::TagRelay(tag) =>
format!("tag-{}", tag), format!("tag-{tag}"),
ActorKind::InstanceRelay(instance) => ActorKind::InstanceRelay(instance) =>
format!("instance-{}", instance), format!("instance-{instance}"),
ActorKind::LanguageRelay(language) => ActorKind::LanguageRelay(language) =>
format!("language-{}", language), format!("language-{language}"),
}), }),
} }
} }

View file

@ -72,7 +72,7 @@ impl ActorCache {
.expect("queues.remove"); .expect("queues.remove");
let queue_len = queue.len(); let queue_len = queue.len();
let mut notified = 0usize; let mut notified = 0usize;
for tx in queue.into_iter() { for tx in queue {
if let Ok(()) = tx.send(result.clone()) { if let Ok(()) = tx.send(result.clone()) {
notified += 1; notified += 1;
} }

View file

@ -3,7 +3,7 @@ use http_digest_headers::{DigestHeader, DigestMethod};
pub fn generate_header(body: &[u8]) -> Result<String, ()> { pub fn generate_header(body: &[u8]) -> Result<String, ()> {
let mut digest_header = DigestHeader::new() let mut digest_header = DigestHeader::new()
.with_method(DigestMethod::SHA256, body) .with_method(DigestMethod::SHA256, body)
.map(|h| format!("{}", h)) .map(|h| format!("{h}"))
.map_err(|_| ())?; .map_err(|_| ())?;
// mastodon expects uppercase algo name // mastodon expects uppercase algo name

View file

@ -37,12 +37,10 @@ where
async fn from_request(req: Request<Body>, state: &S) -> Result<Self, Self::Rejection> { async fn from_request(req: Request<Body>, state: &S) -> Result<Self, Self::Rejection> {
// validate content-type // validate content-type
let content_type = if let Some(content_type) = req.headers() let Some(content_type) = req.headers()
.get(CONTENT_TYPE) .get(CONTENT_TYPE)
.and_then(|value| value.to_str().ok()) .and_then(|value| value.to_str().ok())
.and_then(|value| value.split(';').next()) { .and_then(|value| value.split(';').next()) else {
content_type
} else {
return Err((StatusCode::UNSUPPORTED_MEDIA_TYPE, "No content-type".to_string())); return Err((StatusCode::UNSUPPORTED_MEDIA_TYPE, "No content-type".to_string()));
}; };
if ! (content_type.starts_with("application/json") || if ! (content_type.starts_with("application/json") ||
@ -57,7 +55,7 @@ where
.ok_or((StatusCode::BAD_REQUEST, "No signed headers".to_string()))?; .ok_or((StatusCode::BAD_REQUEST, "No signed headers".to_string()))?;
for header in SIGNATURE_HEADERS_REQUIRED { for header in SIGNATURE_HEADERS_REQUIRED {
if !signature_headers.iter().any(|h| h == header) { if !signature_headers.iter().any(|h| h == header) {
return Err((StatusCode::BAD_REQUEST, format!("Header {:?} not signed", header))); return Err((StatusCode::BAD_REQUEST, format!("Header {header:?} not signed")));
} }
} }
@ -75,10 +73,10 @@ where
digest_header = digest_header.replace('+', "-") digest_header = digest_header.replace('+', "-")
.replace('/', "_"); .replace('/', "_");
let digest: DigestHeader = digest_header.parse() let digest: DigestHeader = digest_header.parse()
.map_err(|e| (StatusCode::BAD_REQUEST, format!("Cannot parse Digest: header: {}", e)))?; .map_err(|e| (StatusCode::BAD_REQUEST, format!("Cannot parse Digest: header: {e}")))?;
// read body // read body
let bytes = Bytes::from_request(req, state).await let bytes = Bytes::from_request(req, state).await
.map_err(|e| (StatusCode::BAD_REQUEST, format!("Body: {}", e)))?; .map_err(|e| (StatusCode::BAD_REQUEST, format!("Body: {e}")))?;
// validate digest // validate digest
if ! digest.verify(&bytes).unwrap_or(false) { if ! digest.verify(&bytes).unwrap_or(false) {
return Err((StatusCode::BAD_REQUEST, "Digest didn't match".to_string())); return Err((StatusCode::BAD_REQUEST, "Digest didn't match".to_string()));

View file

@ -39,12 +39,9 @@ fn track_request(method: &'static str, controller: &'static str, result: &'stati
async fn webfinger( async fn webfinger(
Query(params): Query<HashMap<String, String>>, Query(params): Query<HashMap<String, String>>,
) -> Response { ) -> Response {
let resource = match params.get("resource") { let Some(resource) = params.get("resource") else {
Some(resource) => resource, track_request("GET", "webfinger", "invalid");
None => { return StatusCode::NOT_FOUND.into_response();
track_request("GET", "webfinger", "invalid");
return StatusCode::NOT_FOUND.into_response();
},
}; };
let Some(target) = Actor::from_uri(resource) else { let Some(target) = Actor::from_uri(resource) else {
track_request("GET", "webfinger", "not_found"); track_request("GET", "webfinger", "not_found");
@ -176,7 +173,7 @@ async fn post_relay(
tracing::error!("post_relay bad action: {e:?}"); tracing::error!("post_relay bad action: {e:?}");
return ( return (
StatusCode::BAD_REQUEST, StatusCode::BAD_REQUEST,
format!("Bad action: {:?}", e) format!("Bad action: {e:?}")
).into_response(); ).into_response();
} }
}; };
@ -275,7 +272,7 @@ async fn post_relay(
tracing::error!("del_follow: {}", e); tracing::error!("del_follow: {}", e);
track_request("POST", "relay", "unfollow_error"); track_request("POST", "relay", "unfollow_error");
(StatusCode::INTERNAL_SERVER_ERROR, (StatusCode::INTERNAL_SERVER_ERROR,
format!("{}", e) format!("{e}")
).into_response() ).into_response()
} }
} }
@ -288,7 +285,7 @@ async fn post_relay(
} }
} }
/// An empty ActivityStreams outbox just to satisfy the spec /// An empty `ActivityStreams` outbox just to satisfy the spec
async fn outbox() -> Response { async fn outbox() -> Response {
Json(json!({ Json(json!({
"@context": "https://www.w3.org/ns/activitystreams", "@context": "https://www.w3.org/ns/activitystreams",
@ -342,7 +339,7 @@ async fn nodeinfo(axum::extract::State(state): axum::extract::State<State>) -> R
})).into_response() })).into_response()
} }
/// Expected by AodeRelay /// Expected by `AodeRelay`
async fn instanceinfo() -> Response { async fn instanceinfo() -> Response {
Json(json!({ Json(json!({
"title": env!("CARGO_PKG_NAME"), "title": env!("CARGO_PKG_NAME"),

View file

@ -111,8 +111,8 @@ fn spawn_worker(client: Arc<reqwest::Client>) -> Sender<Job> {
let mut last_request = None; let mut last_request = None;
while let Some(Job { post_url, actor_id, key_id, private_key, body, inbox_url }) = rx.next().await { while let Some(Job { post_url, actor_id, key_id, private_key, body, inbox_url }) = rx.next().await {
if errors > 0 && last_request.map_or(false, |last_request| if errors > 0 && last_request.map_or(false, |last_request: Instant|
Instant::now() - last_request < Duration::from_secs(10) * errors last_request.elapsed() < Duration::from_secs(10) * errors
) { ) {
// there have been errors, skip for time proportional // there have been errors, skip for time proportional
// to the number of subsequent errors // to the number of subsequent errors
@ -162,13 +162,12 @@ pub fn spawn(
continue; continue;
} }
}; };
let post_url = match post.url { let post_url = if let Some(url) = post.url {
Some(ref url) => Arc::new(url.to_string()), Arc::new(url.to_string())
} else {
// skip reposts // skip reposts
None => { increment_counter!("relay_posts_total", "action" => "skip");
increment_counter!("relay_posts_total", "action" => "skip"); continue;
continue;
}
}; };
let mut seen_actors = HashSet::new(); let mut seen_actors = HashSet::new();
let mut seen_inboxes = HashSet::new(); let mut seen_inboxes = HashSet::new();

View file

@ -31,7 +31,7 @@ impl State {
database, database,
redis: redis.map(|(connection, in_topic)| (connection, Arc::new(in_topic))), redis: redis.map(|(connection, in_topic)| (connection, Arc::new(in_topic))),
client: Arc::new(client), client: Arc::new(client),
actor_cache: Default::default(), actor_cache: ActorCache::default(),
hostname: Arc::new(config.hostname), hostname: Arc::new(config.hostname),
priv_key, priv_key,
pub_key, pub_key,