api: Only percent-encode reserved characters in endpoint URL path

This commit is contained in:
Kévin Commaille 2023-01-16 13:07:33 +01:00 committed by GitHub
parent b859d9c8b0
commit 48288865db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 32 additions and 3 deletions

View File

@ -229,7 +229,7 @@ pub mod v3 {
assert_eq!( assert_eq!(
req.uri(), req.uri(),
"https://server.tld/_matrix/client/v3/rooms/%21room%3Aserver%2Etld/state/m%2Eroom%2Ename/" "https://server.tld/_matrix/client/v3/rooms/!room:server.tld/state/m.room.name/"
); );
} }
} }

View File

@ -11,6 +11,7 @@ Bug fixes:
* Fix deserialization of `StateUnsigned` when the `prev_content` is redacted * Fix deserialization of `StateUnsigned` when the `prev_content` is redacted
* Allow to deserialize `PushCondition` with unknown kind * Allow to deserialize `PushCondition` with unknown kind
* Allow to deserialize `push::Action` with unknown value * Allow to deserialize `push::Action` with unknown value
* Only percent-encode reserved characters in endpoint URL path
Breaking changes: Breaking changes:

View File

@ -9,7 +9,7 @@ use http::{
header::{self, HeaderName, HeaderValue}, header::{self, HeaderName, HeaderValue},
Method, Method,
}; };
use percent_encoding::utf8_percent_encode; use percent_encoding::{utf8_percent_encode, AsciiSet, CONTROLS};
use tracing::warn; use tracing::warn;
use super::{ use super::{
@ -18,6 +18,19 @@ use super::{
}; };
use crate::{serde::slice_to_buf, RoomVersionId}; use crate::{serde::slice_to_buf, RoomVersionId};
// The path percent-encode set as defined in the WHATWG URL standard
// <https://url.spec.whatwg.org/#path-percent-encode-set>
const PATH_PERCENT_ENCODE_SET: &AsciiSet = &CONTROLS
.add(b' ')
.add(b'"')
.add(b'#')
.add(b'<')
.add(b'>')
.add(b'?')
.add(b'`')
.add(b'{')
.add(b'}');
/// Metadata about an API endpoint. /// Metadata about an API endpoint.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
#[allow(clippy::exhaustive_structs)] #[allow(clippy::exhaustive_structs)]
@ -101,7 +114,7 @@ impl Metadata {
.next() .next()
.expect("number of placeholders must match number of arguments") .expect("number of placeholders must match number of arguments")
.to_string(); .to_string();
let arg = utf8_percent_encode(&arg, percent_encoding::NON_ALPHANUMERIC); let arg = utf8_percent_encode(&arg, PATH_PERCENT_ENCODE_SET);
write!(res, "/{arg}").expect("writing to a String using fmt::Write can't fail"); write!(res, "/{arg}").expect("writing to a String using fmt::Write can't fail");
} else { } else {
@ -708,6 +721,21 @@ mod tests {
assert_eq!(url, "https://example.org/s/123"); assert_eq!(url, "https://example.org/s/123");
} }
#[test]
fn make_endpoint_url_with_path_args_with_dash() {
let meta = stable_only_metadata(&[(V1_0, "/s/:x")]);
let url =
meta.make_endpoint_url(&[V1_0], "https://example.org", &[&"my-path"], "").unwrap();
assert_eq!(url, "https://example.org/s/my-path");
}
#[test]
fn make_endpoint_url_with_path_args_with_reserved_char() {
let meta = stable_only_metadata(&[(V1_0, "/s/:x")]);
let url = meta.make_endpoint_url(&[V1_0], "https://example.org", &[&"#path"], "").unwrap();
assert_eq!(url, "https://example.org/s/%23path");
}
#[test] #[test]
fn make_endpoint_url_with_query() { fn make_endpoint_url_with_query() {
let meta = stable_only_metadata(&[(V1_0, "/s/")]); let meta = stable_only_metadata(&[(V1_0, "/s/")]);