Use incoming endpoint instead of hardcoded localhost
This commit is contained in:
parent
8f6e7a0d02
commit
c5eeb147a5
|
@ -13,7 +13,7 @@ pub(crate) async fn receive_c2s_gemention(
|
|||
) -> Result<MentionResponse, GementionError> {
|
||||
let mention_upload = C2SMentionRequest::try_from(&client)?.validate()?;
|
||||
let mut mention = Mention::try_from(mention_upload)?;
|
||||
verify(&client.url, &mut mention).await?;
|
||||
verify(&mut mention).await?;
|
||||
|
||||
Ok(MentionResponse::from(mention))
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ pub(crate) async fn receive_s2s_gemention(
|
|||
) -> Result<MentionResponse, GementionError> {
|
||||
let mention_upload = C2SMentionRequest::try_from(&client)?;
|
||||
let mut mention = Mention::try_from(mention_upload)?;
|
||||
verify(&client.url, &mut mention).await?;
|
||||
verify(&mut mention).await?;
|
||||
|
||||
Ok(MentionResponse::from(mention))
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ fn parse_content_body(raw_body: &[u8]) -> Result<&str, GementionError> {
|
|||
/// gemention.
|
||||
pub(crate) struct C2SMentionRequest<'a> {
|
||||
client: &'a Client,
|
||||
receiving_endpoint: &'a Url,
|
||||
accessed_url: &'a Url,
|
||||
}
|
||||
|
||||
impl<'a> C2SMentionRequest<'a> {
|
||||
|
@ -41,7 +41,7 @@ impl<'a> C2SMentionRequest<'a> {
|
|||
if let Some(_) = client.titan {
|
||||
Ok(Self {
|
||||
client: &client,
|
||||
receiving_endpoint: &client.url,
|
||||
accessed_url: &client.url,
|
||||
})
|
||||
} else {
|
||||
Err(GementionError::NotTitanResource)
|
||||
|
@ -84,8 +84,9 @@ impl<'a> C2SMentionRequest<'a> {
|
|||
parse_content_body(self.raw_body())
|
||||
}
|
||||
|
||||
pub fn receiving_endpoint(&self) -> &Url {
|
||||
self.receiving_endpoint
|
||||
/// The full URL that was accessed for the incoming request.
|
||||
pub fn accessed_url(&self) -> &Url {
|
||||
self.accessed_url
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -105,6 +106,7 @@ pub(crate) enum MentionType {
|
|||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct Mention {
|
||||
receiving_endpoint: Url,
|
||||
mention_type: MentionType,
|
||||
target: String,
|
||||
user: String,
|
||||
|
@ -117,6 +119,10 @@ impl Mention {
|
|||
&self.target
|
||||
}
|
||||
|
||||
pub fn receiving_endpoint(&self) -> &Url {
|
||||
&self.receiving_endpoint
|
||||
}
|
||||
|
||||
pub fn target_url(&self) -> Url {
|
||||
Url::parse(&format!("gemini://{}", &self.target)).unwrap()
|
||||
}
|
||||
|
@ -223,6 +229,15 @@ impl<'a> TryFrom<C2SMentionRequest<'a>> for Mention {
|
|||
.username()
|
||||
.ok_or(GementionError::UsernameNotProvided)?;
|
||||
|
||||
let receiving_endpoint = Url::parse(
|
||||
resource
|
||||
.accessed_url()
|
||||
.as_str()
|
||||
.split(&target)
|
||||
.next()
|
||||
.ok_or(GementionError::InvalidBody)?,
|
||||
)?;
|
||||
|
||||
let content = resource.content()?.to_owned();
|
||||
let content = if !content.is_empty() {
|
||||
Some(content)
|
||||
|
@ -235,6 +250,7 @@ impl<'a> TryFrom<C2SMentionRequest<'a>> for Mention {
|
|||
mention_type,
|
||||
content,
|
||||
target,
|
||||
receiving_endpoint,
|
||||
verification_status: VerificationStatus::NotYetVerified,
|
||||
})
|
||||
} else {
|
||||
|
|
|
@ -48,7 +48,7 @@ pub(crate) enum VerificationFailureReason {
|
|||
|
||||
/// One or more mention links exist, but they are not to this
|
||||
/// endpoint, or for this page.
|
||||
MentionLinkIncorrect,
|
||||
MentionLinkIncorrect(String),
|
||||
|
||||
/// There was an error during the verification process.
|
||||
Error(GementionError),
|
||||
|
@ -58,7 +58,9 @@ impl ToString for VerificationFailureReason {
|
|||
fn to_string(&self) -> String {
|
||||
match self {
|
||||
Self::NoMentionLinkFound => String::from("No mention link found"),
|
||||
Self::MentionLinkIncorrect => String::from("Mention link points to wrong target"),
|
||||
Self::MentionLinkIncorrect(endpoint) => {
|
||||
format!("Target URL does not accept gementions from endpoint: {}", endpoint)
|
||||
}
|
||||
Self::Error(err) => err.to_string(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,13 +7,12 @@ use crate::error::GementionError;
|
|||
use crate::models::mentions::Mention;
|
||||
use crate::models::verification::*;
|
||||
|
||||
const OUR_ENDPOINT: &'static str = "titan://localhost/receive/";
|
||||
|
||||
fn is_mention_link(gemtext_link: &str) -> bool {
|
||||
gemtext_link.starts_with(OUR_ENDPOINT)
|
||||
fn is_mention_link(endpoint: &Url, gemtext_link: &str) -> bool {
|
||||
gemtext_link.starts_with(endpoint.as_str())
|
||||
}
|
||||
|
||||
fn scan_for_gemention_endpoints(
|
||||
endpoint: &Url,
|
||||
meta: GeminiMetadata,
|
||||
ast: GeminiAst,
|
||||
) -> (VerificationSource, Vec<String>) {
|
||||
|
@ -29,7 +28,7 @@ fn scan_for_gemention_endpoints(
|
|||
.inner()
|
||||
.into_iter()
|
||||
.filter_map(|node| match node {
|
||||
GemtextNode::Link { ref to, .. } if is_mention_link(to) => Some(to),
|
||||
GemtextNode::Link { ref to, .. } if is_mention_link(endpoint, to) => Some(to),
|
||||
_ => None,
|
||||
})
|
||||
.cloned()
|
||||
|
@ -38,14 +37,17 @@ fn scan_for_gemention_endpoints(
|
|||
(VerificationSource::Page, endpoints)
|
||||
}
|
||||
|
||||
fn verify_mentions<S: AsRef<str>>(
|
||||
expected_link: S,
|
||||
fn verify_mentions(
|
||||
mention: &mut Mention,
|
||||
source_and_endpoints: (VerificationSource, Vec<String>),
|
||||
) -> VerificationStatus {
|
||||
) -> Result<VerificationStatus, GementionError> {
|
||||
let (verification_source, mentions) = source_and_endpoints;
|
||||
// TODO need to normalize url from page as well as ours, to make
|
||||
// sure things like ports being in url or not are handled.
|
||||
let expected_link = mention.receiving_endpoint().join(mention.target())?;
|
||||
let expected_link = expected_link.as_ref();
|
||||
|
||||
if mentions.len() > 0 {
|
||||
let verification_status = if mentions.len() > 0 {
|
||||
// We have links that go to our endpoint. Scan links for the
|
||||
// one we expect (i.e. for the target), otherwise we say
|
||||
// incorrect link.
|
||||
|
@ -62,16 +64,19 @@ fn verify_mentions<S: AsRef<str>>(
|
|||
}
|
||||
})
|
||||
.unwrap_or(VerificationStatus::Invalid(
|
||||
VerificationFailureReason::MentionLinkIncorrect,
|
||||
VerificationFailureReason::MentionLinkIncorrect(
|
||||
mention.receiving_endpoint().to_string(),
|
||||
),
|
||||
))
|
||||
} else {
|
||||
VerificationStatus::Invalid(VerificationFailureReason::NoMentionLinkFound)
|
||||
}
|
||||
};
|
||||
|
||||
Ok(verification_status)
|
||||
}
|
||||
|
||||
async fn verify_mention(expected_link: &Url, mention: &mut Mention) -> Result<(), GementionError> {
|
||||
async fn verify_mention(mention: &mut Mention) -> Result<(), GementionError> {
|
||||
let url = Url::parse(&format!("gemini://{}", mention.target()))?;
|
||||
println!("expected link is {}", expected_link);
|
||||
|
||||
let resp = germ_request(&url).await?;
|
||||
let meta = GeminiMetadata::from_string(resp.meta());
|
||||
|
@ -82,13 +87,14 @@ async fn verify_mention(expected_link: &Url, mention: &mut Mention) -> Result<()
|
|||
.ok_or(GementionError::NoContentFoundForTarget)?;
|
||||
|
||||
let ast = GeminiAst::from_string(content);
|
||||
let source_and_endpoints = scan_for_gemention_endpoints(meta, ast);
|
||||
let status = verify_mentions(expected_link, source_and_endpoints);
|
||||
let source_and_endpoints =
|
||||
scan_for_gemention_endpoints(mention.receiving_endpoint(), meta, ast);
|
||||
let status = verify_mentions(mention, source_and_endpoints)?;
|
||||
|
||||
mention.set_verify_status(status);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) async fn verify(expected_url: &Url, mention: &mut Mention) -> Result<(), GementionError> {
|
||||
verify_mention(expected_url, mention).await
|
||||
pub(crate) async fn verify(mention: &mut Mention) -> Result<(), GementionError> {
|
||||
verify_mention(mention).await
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue