feat: support hosting .well-known from Conduit
Co-authored-by: Matthias Ahouansou <matthias@ahouansou.cz>
This commit is contained in:
parent
b4a60c3f9a
commit
c1f695653b
10 changed files with 101 additions and 23 deletions
3
Cargo.lock
generated
3
Cargo.lock
generated
|
@ -432,6 +432,8 @@ dependencies = [
|
||||||
"tracing-flame",
|
"tracing-flame",
|
||||||
"tracing-opentelemetry",
|
"tracing-opentelemetry",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
|
"trust-dns-resolver",
|
||||||
|
"url",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -3124,6 +3126,7 @@ dependencies = [
|
||||||
"form_urlencoded",
|
"form_urlencoded",
|
||||||
"idna 0.5.0",
|
"idna 0.5.0",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -107,6 +107,9 @@ futures-util = { version = "0.3.28", default-features = false }
|
||||||
# Used for reading the configuration from conduit.toml & environment variables
|
# Used for reading the configuration from conduit.toml & environment variables
|
||||||
figment = { version = "0.10.8", features = ["env", "toml"] }
|
figment = { version = "0.10.8", features = ["env", "toml"] }
|
||||||
|
|
||||||
|
# Validating urls in config
|
||||||
|
url = { version = "2", features = ["serde"] }
|
||||||
|
|
||||||
tikv-jemallocator = { version = "0.5.0", features = ["unprefixed_malloc_on_supported_platforms"], optional = true }
|
tikv-jemallocator = { version = "0.5.0", features = ["unprefixed_malloc_on_supported_platforms"], optional = true }
|
||||||
async-trait = "0.1.68"
|
async-trait = "0.1.68"
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
# https://matrix.org/docs/spec/client_server/latest#get-well-known-matrix-client
|
# https://matrix.org/docs/spec/client_server/latest#get-well-known-matrix-client
|
||||||
# and
|
# and
|
||||||
# https://matrix.org/docs/spec/server_server/r0.1.4#get-well-known-matrix-server
|
# https://matrix.org/docs/spec/server_server/r0.1.4#get-well-known-matrix-server
|
||||||
# for more information
|
# for more information, or continue below to see how conduit can do this for you.
|
||||||
|
|
||||||
# YOU NEED TO EDIT THIS
|
# YOU NEED TO EDIT THIS
|
||||||
#server_name = "your.server.name"
|
#server_name = "your.server.name"
|
||||||
|
@ -65,3 +65,10 @@ trusted_servers = ["matrix.org"]
|
||||||
|
|
||||||
address = "127.0.0.1" # This makes sure Conduit can only be reached using the reverse proxy
|
address = "127.0.0.1" # This makes sure Conduit can only be reached using the reverse proxy
|
||||||
#address = "0.0.0.0" # If Conduit is running in a container, make sure the reverse proxy (ie. Traefik) can reach it.
|
#address = "0.0.0.0" # If Conduit is running in a container, make sure the reverse proxy (ie. Traefik) can reach it.
|
||||||
|
|
||||||
|
[global.well_known]
|
||||||
|
# Conduit handles the /.well-known/matrix/* endpoints, making both clients and servers try to access conduit with the host
|
||||||
|
# server_name and port 443 by default.
|
||||||
|
# If you want to override these defaults, uncomment and edit the following lines accordingly:
|
||||||
|
#server = your.server.name:443
|
||||||
|
#client = https://your.server.name
|
||||||
|
|
|
@ -32,6 +32,7 @@ mod typing;
|
||||||
mod unversioned;
|
mod unversioned;
|
||||||
mod user_directory;
|
mod user_directory;
|
||||||
mod voip;
|
mod voip;
|
||||||
|
mod well_known;
|
||||||
|
|
||||||
pub use account::*;
|
pub use account::*;
|
||||||
pub use alias::*;
|
pub use alias::*;
|
||||||
|
@ -67,6 +68,7 @@ pub use typing::*;
|
||||||
pub use unversioned::*;
|
pub use unversioned::*;
|
||||||
pub use user_directory::*;
|
pub use user_directory::*;
|
||||||
pub use voip::*;
|
pub use voip::*;
|
||||||
|
pub use well_known::*;
|
||||||
|
|
||||||
pub const DEVICE_ID_LENGTH: usize = 10;
|
pub const DEVICE_ID_LENGTH: usize = 10;
|
||||||
pub const TOKEN_LENGTH: usize = 32;
|
pub const TOKEN_LENGTH: usize = 32;
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
use std::{collections::BTreeMap, iter::FromIterator};
|
use std::{collections::BTreeMap, iter::FromIterator};
|
||||||
|
|
||||||
use axum::{response::IntoResponse, Json};
|
use ruma::api::client::discovery::get_supported_versions;
|
||||||
use ruma::api::client::{discovery::get_supported_versions, error::ErrorKind};
|
|
||||||
|
|
||||||
use crate::{services, Error, Result, Ruma};
|
use crate::{Result, Ruma};
|
||||||
|
|
||||||
/// # `GET /_matrix/client/versions`
|
/// # `GET /_matrix/client/versions`
|
||||||
///
|
///
|
||||||
|
@ -33,18 +32,3 @@ pub async fn get_supported_versions_route(
|
||||||
|
|
||||||
Ok(resp)
|
Ok(resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `GET /.well-known/matrix/client`
|
|
||||||
pub async fn well_known_client_route(
|
|
||||||
_body: Ruma<get_supported_versions::Request>,
|
|
||||||
) -> Result<impl IntoResponse> {
|
|
||||||
let client_url = match services().globals.well_known_client() {
|
|
||||||
Some(url) => url.clone(),
|
|
||||||
None => return Err(Error::BadRequest(ErrorKind::NotFound, "Not found.")),
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(Json(serde_json::json!({
|
|
||||||
"m.homeserver": {"base_url": client_url},
|
|
||||||
"org.matrix.msc3575.proxy": {"url": client_url}
|
|
||||||
})))
|
|
||||||
}
|
|
||||||
|
|
22
src/api/client_server/well_known.rs
Normal file
22
src/api/client_server/well_known.rs
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
use ruma::api::client::discovery::discover_homeserver::{
|
||||||
|
self, HomeserverInfo, SlidingSyncProxyInfo,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{services, Result, Ruma};
|
||||||
|
|
||||||
|
/// # `GET /.well-known/matrix/client`
|
||||||
|
///
|
||||||
|
/// Returns the client server discovery information.
|
||||||
|
pub async fn well_known_client(
|
||||||
|
_body: Ruma<discover_homeserver::Request>,
|
||||||
|
) -> Result<discover_homeserver::Response> {
|
||||||
|
let client_url = services().globals.well_known_client();
|
||||||
|
|
||||||
|
Ok(discover_homeserver::Response {
|
||||||
|
homeserver: HomeserverInfo {
|
||||||
|
base_url: client_url.clone(),
|
||||||
|
},
|
||||||
|
identity_server: None,
|
||||||
|
sliding_sync_proxy: Some(SlidingSyncProxyInfo { url: client_url }),
|
||||||
|
})
|
||||||
|
}
|
|
@ -17,7 +17,10 @@ use ruma::{
|
||||||
backfill::get_backfill,
|
backfill::get_backfill,
|
||||||
device::get_devices::{self, v1::UserDevice},
|
device::get_devices::{self, v1::UserDevice},
|
||||||
directory::{get_public_rooms, get_public_rooms_filtered},
|
directory::{get_public_rooms, get_public_rooms_filtered},
|
||||||
discovery::{get_server_keys, get_server_version, ServerSigningKeys, VerifyKey},
|
discovery::{
|
||||||
|
discover_homeserver, get_server_keys, get_server_version, ServerSigningKeys,
|
||||||
|
VerifyKey,
|
||||||
|
},
|
||||||
event::{get_event, get_missing_events, get_room_state, get_room_state_ids},
|
event::{get_event, get_missing_events, get_room_state, get_room_state_ids},
|
||||||
keys::{claim_keys, get_keys},
|
keys::{claim_keys, get_keys},
|
||||||
membership::{create_invite, create_join_event, prepare_join_event},
|
membership::{create_invite, create_join_event, prepare_join_event},
|
||||||
|
@ -1910,6 +1913,17 @@ pub async fn claim_keys_route(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// # `GET /.well-known/matrix/server`
|
||||||
|
///
|
||||||
|
/// Returns the federation server discovery information.
|
||||||
|
pub async fn well_known_server(
|
||||||
|
_body: Ruma<discover_homeserver::Request>,
|
||||||
|
) -> Result<discover_homeserver::Response> {
|
||||||
|
Ok(discover_homeserver::Response {
|
||||||
|
server: services().globals.well_known_server(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::{add_port_to_hostname, get_ip_with_port, FedDest};
|
use super::{add_port_to_hostname, get_ip_with_port, FedDest};
|
||||||
|
|
|
@ -7,6 +7,7 @@ use std::{
|
||||||
use ruma::{OwnedServerName, RoomVersionId};
|
use ruma::{OwnedServerName, RoomVersionId};
|
||||||
use serde::{de::IgnoredAny, Deserialize};
|
use serde::{de::IgnoredAny, Deserialize};
|
||||||
use tracing::warn;
|
use tracing::warn;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
mod proxy;
|
mod proxy;
|
||||||
|
|
||||||
|
@ -56,7 +57,8 @@ pub struct Config {
|
||||||
pub allow_unstable_room_versions: bool,
|
pub allow_unstable_room_versions: bool,
|
||||||
#[serde(default = "default_default_room_version")]
|
#[serde(default = "default_default_room_version")]
|
||||||
pub default_room_version: RoomVersionId,
|
pub default_room_version: RoomVersionId,
|
||||||
pub well_known_client: Option<String>,
|
#[serde(default)]
|
||||||
|
pub well_known: WellKnownConfig,
|
||||||
#[serde(default = "false_fn")]
|
#[serde(default = "false_fn")]
|
||||||
pub allow_jaeger: bool,
|
pub allow_jaeger: bool,
|
||||||
#[serde(default = "false_fn")]
|
#[serde(default = "false_fn")]
|
||||||
|
@ -91,6 +93,12 @@ pub struct TlsConfig {
|
||||||
pub key: String,
|
pub key: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, Default)]
|
||||||
|
pub struct WellKnownConfig {
|
||||||
|
pub client: Option<Url>,
|
||||||
|
pub server: Option<OwnedServerName>,
|
||||||
|
}
|
||||||
|
|
||||||
const DEPRECATED_KEYS: &[&str] = &["cache_capacity"];
|
const DEPRECATED_KEYS: &[&str] = &["cache_capacity"];
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
|
@ -111,9 +119,35 @@ impl Config {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Config {
|
||||||
|
pub fn well_known_client(&self) -> String {
|
||||||
|
if let Some(url) = &self.well_known.client {
|
||||||
|
url.to_string()
|
||||||
|
} else {
|
||||||
|
format!("https://{}", self.server_name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn well_known_server(&self) -> OwnedServerName {
|
||||||
|
match &self.well_known.server {
|
||||||
|
Some(server_name) => server_name.to_owned(),
|
||||||
|
None => {
|
||||||
|
if self.server_name.port().is_some() {
|
||||||
|
self.server_name.to_owned()
|
||||||
|
} else {
|
||||||
|
format!("{}:443", self.server_name.host())
|
||||||
|
.try_into()
|
||||||
|
.expect("Host from valid hostname + :443 must be valid")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl fmt::Display for Config {
|
impl fmt::Display for Config {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
// Prepare a list of config values to show
|
// Prepare a list of config values to show
|
||||||
|
let well_known_server = self.well_known_server();
|
||||||
let lines = [
|
let lines = [
|
||||||
("Server name", self.server_name.host()),
|
("Server name", self.server_name.host()),
|
||||||
("Database backend", &self.database_backend),
|
("Database backend", &self.database_backend),
|
||||||
|
@ -194,6 +228,8 @@ impl fmt::Display for Config {
|
||||||
}
|
}
|
||||||
&lst.join(", ")
|
&lst.join(", ")
|
||||||
}),
|
}),
|
||||||
|
("Well-known server name", well_known_server.as_str()),
|
||||||
|
("Well-known client URL", &self.well_known_client()),
|
||||||
];
|
];
|
||||||
|
|
||||||
let mut msg: String = "Active config values:\n\n".to_owned();
|
let mut msg: String = "Active config values:\n\n".to_owned();
|
||||||
|
|
|
@ -390,6 +390,7 @@ fn routes(config: &Config) -> Router {
|
||||||
.ruma_route(client_server::get_relating_events_with_rel_type_route)
|
.ruma_route(client_server::get_relating_events_with_rel_type_route)
|
||||||
.ruma_route(client_server::get_relating_events_route)
|
.ruma_route(client_server::get_relating_events_route)
|
||||||
.ruma_route(client_server::get_hierarchy_route)
|
.ruma_route(client_server::get_hierarchy_route)
|
||||||
|
.ruma_route(client_server::well_known_client)
|
||||||
.route(
|
.route(
|
||||||
"/_matrix/client/r0/rooms/:room_id/initialSync",
|
"/_matrix/client/r0/rooms/:room_id/initialSync",
|
||||||
get(initial_sync),
|
get(initial_sync),
|
||||||
|
@ -430,10 +431,12 @@ fn routes(config: &Config) -> Router {
|
||||||
.ruma_route(server_server::get_profile_information_route)
|
.ruma_route(server_server::get_profile_information_route)
|
||||||
.ruma_route(server_server::get_keys_route)
|
.ruma_route(server_server::get_keys_route)
|
||||||
.ruma_route(server_server::claim_keys_route)
|
.ruma_route(server_server::claim_keys_route)
|
||||||
|
.ruma_route(server_server::well_known_server)
|
||||||
} else {
|
} else {
|
||||||
router
|
router
|
||||||
.route("/_matrix/federation/*path", any(federation_disabled))
|
.route("/_matrix/federation/*path", any(federation_disabled))
|
||||||
.route("/_matrix/key/*path", any(federation_disabled))
|
.route("/_matrix/key/*path", any(federation_disabled))
|
||||||
|
.route("/.well-known/matrix/server", any(federation_disabled))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -417,8 +417,12 @@ impl Service {
|
||||||
r
|
r
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn well_known_client(&self) -> &Option<String> {
|
pub fn well_known_server(&self) -> OwnedServerName {
|
||||||
&self.config.well_known_client
|
self.config.well_known_server()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn well_known_client(&self) -> String {
|
||||||
|
self.config.well_known_client()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn shutdown(&self) {
|
pub fn shutdown(&self) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue