Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changesets/fix_connectors_empty_relative_path_panic.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
### Fix a panic building connector request URIs with an empty or slash-less relative path ([PR #9790](https://github.com/apollographql/router/pull/9790))

Connector request URIs with an empty path and query (no `sourcePath`, `connectPath`, or query params) or with a `connectPath` template lacking a leading `/` could panic the router when built against `http` crate versions 1.4.2 and later, which tightened `PathAndQuery` validation to reject an empty string and require a leading `/` on relative paths.

Connector URI construction now explicitly normalizes these cases (empty becomes `/`, a slash-less relative path gets a leading `/` added) instead of relying on validation behavior that newer `http` versions no longer provide.

By [@aaronArinder](https://github.com/aaronArinder) in https://github.com/apollographql/router/pull/9790
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ impl HttpJsonTransport {
let query = query.into_string();

uri_parts.path_and_query = Some(match (path.is_empty(), query.is_empty()) {
(true, true) => PathAndQuery::from_static(""),
(true, true) => PathAndQuery::from_static("/"),
(true, false) => PathAndQuery::try_from(format!("?{query}"))?,
(false, true) => PathAndQuery::try_from(path)?,
(false, false) => PathAndQuery::try_from(format!("{path}?{query}"))?,
Expand Down
15 changes: 13 additions & 2 deletions apollo-federation/src/connectors/string_template.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,19 @@ impl StringTemplate {
let uri = if result.contains("://") {
Uri::from_str(result.as_ref())
} else {
// Explicitly set this as a relative URI so it doesn't get confused for a domain name
PathAndQuery::from_str(result.as_ref()).map(Uri::from)
// Explicitly set this as a relative URI so it doesn't get confused for a domain name.
// `PathAndQuery` rejects an empty string and requires a leading `/` (or `?` for a
// query-only value); normalize here rather than relying on the caller to have
// written a template that already starts with `/`.
let relative = result.as_ref();
let relative = if relative.is_empty() {
"/".to_string()
} else if relative.starts_with('/') || relative.starts_with('?') {
relative.to_string()
} else {
format!("/{relative}")
};
PathAndQuery::from_str(&relative).map(Uri::from)
}
.map_err(|err| Error {
message: format!("Invalid URI: {err}"),
Expand Down
Loading