diff --git a/src/activity_sending.rs b/src/activity_sending.rs index 1c84757..83fdcfe 100644 --- a/src/activity_sending.rs +++ b/src/activity_sending.rs @@ -12,7 +12,7 @@ use crate::{ }; use bytes::Bytes; use futures::StreamExt; -use http::StatusCode; +use http::{header::USER_AGENT, StatusCode}; use httpdate::fmt_http_date; use itertools::Itertools; use reqwest::{ @@ -39,6 +39,7 @@ pub struct SendActivityTask { pub(crate) inbox: Url, pub(crate) private_key: RsaPrivateKey, pub(crate) http_signature_compat: bool, + pub(crate) user_agent: String, } impl Display for SendActivityTask { @@ -83,7 +84,7 @@ impl SendActivityTask { let request_builder = client .post(self.inbox.to_string()) .timeout(timeout) - .headers(generate_request_headers(&self.inbox)); + .headers(generate_request_headers(&self.inbox, &self.user_agent)); let request = sign_request( request_builder, &self.actor_id, @@ -173,6 +174,7 @@ where activity: activity_serialized.clone(), private_key: private_key.clone(), http_signature_compat: config.http_signature_compat, + user_agent: config.user_agent().to_owned(), }) }) .collect() @@ -211,7 +213,7 @@ where .map_err(|e| Error::Other(format!("cloned error: {e}"))) } -pub(crate) fn generate_request_headers(inbox_url: &Url) -> HeaderMap { +pub(crate) fn generate_request_headers(inbox_url: &Url, user_agent: &str) -> HeaderMap { let mut host = inbox_url.domain().expect("read inbox domain").to_string(); if let Some(port) = inbox_url.port() { host = format!("{}:{}", host, port); @@ -222,6 +224,11 @@ pub(crate) fn generate_request_headers(inbox_url: &Url) -> HeaderMap { HeaderName::from_static("content-type"), HeaderValue::from_static(FEDERATION_CONTENT_TYPE), ); + + headers.insert( + USER_AGENT, + HeaderValue::from_str(user_agent).expect("Hostname is valid"), + ); headers.insert( HeaderName::from_static("host"), HeaderValue::from_str(&host).expect("Hostname is valid"), @@ -230,6 +237,7 @@ pub(crate) fn generate_request_headers(inbox_url: &Url) -> HeaderMap { "date", HeaderValue::from_str(&fmt_http_date(SystemTime::now())).expect("Date is valid"), ); + println!("Generating request headers: {:?}", headers); headers } diff --git a/src/config.rs b/src/config.rs index 2015750..4331293 100644 --- a/src/config.rs +++ b/src/config.rs @@ -191,6 +191,11 @@ impl FederationConfig { pub fn domain(&self) -> &str { &self.domain } + + /// Returns user-agent + pub fn user_agent(&self) -> &str { + &self.domain + } } impl FederationConfigBuilder { diff --git a/src/fetch/mod.rs b/src/fetch/mod.rs index b8e9c84..c58e0fe 100644 --- a/src/fetch/mod.rs +++ b/src/fetch/mod.rs @@ -11,7 +11,7 @@ use crate::{ FEDERATION_CONTENT_TYPE, }; use bytes::Bytes; -use http::{HeaderValue, StatusCode}; +use http::{header::USER_AGENT, HeaderValue, StatusCode}; use serde::de::DeserializeOwned; use std::sync::atomic::Ordering; use tracing::info; @@ -115,6 +115,7 @@ async fn fetch_object_http_with_accept( .client .get(url.as_str()) .header("Accept", content_type) + .header(USER_AGENT, data.config.user_agent()) .timeout(config.request_timeout); let res = if let Some((actor_id, private_key_pem)) = config.signed_fetch_actor.as_deref() {