Use Url instead of String

This commit is contained in:
Felix Ableitner 2020-04-08 14:37:05 +02:00
parent 45d13145b5
commit 3320c2d651
6 changed files with 42 additions and 37 deletions

1
server/Cargo.lock generated vendored
View file

@ -2743,6 +2743,7 @@ dependencies = [
"idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.105 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]

2
server/Cargo.toml vendored
View file

@ -34,7 +34,7 @@ rss = "1.9.0"
htmlescape = "0.3.1"
config = "0.10.1"
hjson = "0.8.2"
url = "2.1.1"
url = { version = "2.1.1", features = ["serde"] }
percent-encoding = "2.1.0"
isahc = "0.9"
comrak = "0.7"

View file

@ -22,6 +22,7 @@ use diesel::r2d2::{ConnectionManager, Pool};
use diesel::PgConnection;
use failure::Error;
use serde::Deserialize;
use url::Url;
#[derive(Deserialize)]
pub struct CommunityQuery {
@ -87,16 +88,14 @@ impl Community {
impl CommunityForm {
pub fn from_group(group: &GroupExt, conn: &PgConnection) -> Result<Self, Error> {
let followers_uri = &group.extension.get_followers().unwrap().to_string();
let outbox_uri = &group.extension.get_outbox().to_string();
let _outbox = fetch_remote_object::<OrderedCollection>(outbox_uri)?;
let _followers = fetch_remote_object::<UnorderedCollection>(followers_uri)?;
let followers_uri = Url::parse(&group.extension.get_followers().unwrap().to_string())?;
let outbox_uri = Url::parse(&group.extension.get_outbox().to_string())?;
let _outbox = fetch_remote_object::<OrderedCollection>(&outbox_uri)?;
let _followers = fetch_remote_object::<UnorderedCollection>(&followers_uri)?;
let oprops = &group.base.object_props;
let aprops = &group.extension;
let creator = fetch_remote_user(
&oprops.get_attributed_to_xsd_any_uri().unwrap().to_string(),
conn,
)?;
let apub_id = Url::parse(&oprops.get_attributed_to_xsd_any_uri().unwrap().to_string())?;
let creator = fetch_remote_user(&apub_id, conn)?;
Ok(CommunityForm {
name: oprops.get_name_xsd_string().unwrap().to_string(),
title: aprops.get_preferred_username().unwrap().to_string(),

View file

@ -12,6 +12,7 @@ use diesel::r2d2::{ConnectionManager, Pool};
use diesel::PgConnection;
use failure::Error;
use serde::Deserialize;
use url::Url;
#[derive(Deserialize)]
pub struct PostQuery {
@ -64,10 +65,8 @@ impl Post {
impl PostForm {
pub fn from_page(page: &Page, conn: &PgConnection) -> Result<PostForm, Error> {
let oprops = &page.object_props;
let creator = fetch_remote_user(
&oprops.get_attributed_to_xsd_any_uri().unwrap().to_string(),
conn,
)?;
let apub_id = Url::parse(&oprops.get_attributed_to_xsd_any_uri().unwrap().to_string())?;
let creator = fetch_remote_user(&apub_id, conn)?;
Ok(PostForm {
name: oprops.get_name_xsd_string().unwrap().to_string(),
url: oprops.get_url_xsd_any_uri().map(|u| u.to_string()),

View file

@ -15,22 +15,23 @@ use isahc::prelude::*;
use log::warn;
use serde::Deserialize;
use std::time::Duration;
use url::Url;
fn fetch_node_info(domain: &str) -> Result<NodeInfo, Error> {
let well_known_uri = format!(
let well_known_uri = Url::parse(&format!(
"{}://{}/.well-known/nodeinfo",
get_apub_protocol_string(),
domain
);
))?;
let well_known = fetch_remote_object::<NodeInfoWellKnown>(&well_known_uri)?;
Ok(fetch_remote_object::<NodeInfo>(&well_known.links.href)?)
}
fn fetch_communities_from_instance(
community_list_url: &str,
community_list: &Url,
conn: &PgConnection,
) -> Result<Vec<Community>, Error> {
fetch_remote_object::<UnorderedCollection>(community_list_url)?
fetch_remote_object::<UnorderedCollection>(community_list)?
.collection_props
.get_many_items_base_boxes()
.unwrap()
@ -53,16 +54,16 @@ fn fetch_communities_from_instance(
}
// TODO: add an optional param last_updated and only fetch if its too old
pub fn fetch_remote_object<Response>(uri: &str) -> Result<Response, Error>
pub fn fetch_remote_object<Response>(url: &Url) -> Result<Response, Error>
where
Response: for<'de> Deserialize<'de>,
{
if Settings::get().federation.tls_enabled && !uri.starts_with("https://") {
return Err(format_err!("Activitypub uri is insecure: {}", uri));
if Settings::get().federation.tls_enabled && url.scheme() != "https" {
return Err(format_err!("Activitypub uri is insecure: {}", url));
}
// TODO: this function should return a future
let timeout = Duration::from_secs(60);
let text = Request::get(uri)
let text = Request::get(url.as_str())
.header("Accept", APUB_JSON_CONTENT_TYPE)
.connect_timeout(timeout)
.timeout(timeout)
@ -78,11 +79,14 @@ fn fetch_remote_community_posts(
community: &Community,
conn: &PgConnection,
) -> Result<Vec<Post>, Error> {
let endpoint = format!("http://{}/federation/c/{}", instance, community.name);
let endpoint = Url::parse(&format!(
"http://{}/federation/c/{}",
instance, community.name
))?;
let group = fetch_remote_object::<GroupExt>(&endpoint)?;
let outbox_uri = &group.extension.get_outbox().to_string();
let outbox_uri = Url::parse(&group.extension.get_outbox().to_string())?;
// TODO: outbox url etc should be stored in local db
let outbox = fetch_remote_object::<OrderedCollection>(outbox_uri)?;
let outbox = fetch_remote_object::<OrderedCollection>(&outbox_uri)?;
let items = outbox.collection_props.get_many_items_base_boxes();
Ok(
@ -106,7 +110,7 @@ fn fetch_remote_community_posts(
)
}
pub fn fetch_remote_user(apub_id: &str, conn: &PgConnection) -> Result<User_, Error> {
pub fn fetch_remote_user(apub_id: &Url, conn: &PgConnection) -> Result<User_, Error> {
let person = fetch_remote_object::<PersonExt>(apub_id)?;
let uf = UserForm::from_person(&person)?;
let existing = User_::read_from_apub_id(conn, &uf.actor_id);
@ -122,8 +126,8 @@ pub fn fetch_remote_user(apub_id: &str, conn: &PgConnection) -> Result<User_, Er
pub fn fetch_all(conn: &PgConnection) -> Result<(), Error> {
for instance in &get_following_instances() {
let node_info = fetch_node_info(instance)?;
if let Some(community_list_url) = node_info.metadata.community_list_url {
let communities = fetch_communities_from_instance(&community_list_url, conn)?;
if let Some(community_list) = node_info.metadata.community_list_url {
let communities = fetch_communities_from_instance(&community_list, conn)?;
for c in communities {
fetch_remote_community_posts(instance, &c, conn)?;
}

View file

@ -7,8 +7,10 @@ use actix_web::web;
use actix_web::HttpResponse;
use diesel::r2d2::{ConnectionManager, Pool};
use diesel::PgConnection;
use failure::Error;
use serde::{Deserialize, Serialize};
use std::fmt::Debug;
use url::Url;
pub fn config(cfg: &mut web::ServiceConfig) {
cfg
@ -16,18 +18,18 @@ pub fn config(cfg: &mut web::ServiceConfig) {
.route("/.well-known/nodeinfo", web::get().to(node_info_well_known));
}
async fn node_info_well_known() -> HttpResponse<Body> {
async fn node_info_well_known() -> Result<HttpResponse<Body>, Error> {
let node_info = NodeInfoWellKnown {
links: NodeInfoWellKnownLinks {
rel: "http://nodeinfo.diaspora.software/ns/schema/2.0".to_string(),
href: format!(
rel: Url::parse("http://nodeinfo.diaspora.software/ns/schema/2.0")?,
href: Url::parse(&format!(
"{}://{}/nodeinfo/2.0.json",
get_apub_protocol_string(),
Settings::get().hostname
),
))?,
},
};
HttpResponse::Ok().json(node_info)
Ok(HttpResponse::Ok().json(node_info))
}
async fn node_info(
@ -60,11 +62,11 @@ async fn node_info(
open_registrations: site_view.open_registration,
},
metadata: NodeInfoMetadata {
community_list_url: Some(format!(
community_list_url: Some(Url::parse(&format!(
"{}://{}/federation/communities",
get_apub_protocol_string(),
Settings::get().hostname
)),
))?),
},
})
})
@ -81,8 +83,8 @@ pub struct NodeInfoWellKnown {
#[derive(Serialize, Deserialize, Debug)]
pub struct NodeInfoWellKnownLinks {
pub rel: String,
pub href: String,
pub rel: Url,
pub href: Url,
}
#[derive(Serialize, Deserialize, Debug)]
@ -116,5 +118,5 @@ pub struct NodeInfoUsers {
#[derive(Serialize, Deserialize, Debug)]
pub struct NodeInfoMetadata {
pub community_list_url: Option<String>,
pub community_list_url: Option<Url>,
}