Skip to content
This repository has been archived by the owner on Sep 21, 2024. It is now read-only.

Commit

Permalink
chore: Revert "feat: Rewrite host headers in API client to embed sphe…
Browse files Browse the repository at this point in the history
…re identity in subdomain when feature 'test-gateway' is enabled." (#754)

This reverts commit da91223.
  • Loading branch information
jsantell authored Jan 8, 2024
1 parent baca775 commit dcabe66
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 113 deletions.
1 change: 0 additions & 1 deletion rust/noosphere-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ readme = "README.md"
default = []
sentry = ["dep:sentry-tracing"]
helpers = []
test-gateway = []

[dependencies]
tracing = { workspace = true }
Expand Down
130 changes: 18 additions & 112 deletions rust/noosphere-core/src/api/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ use noosphere_storage::{block_deserialize, block_serialize, BlockStore};
use reqwest::{header::HeaderMap, StatusCode};
use tokio_stream::{Stream, StreamExt};
use tokio_util::io::StreamReader;
use tracing::*;
use ucan::{
builder::UcanBuilder,
capability::CapabilityView,
Expand All @@ -31,7 +30,7 @@ use ucan::{
};
use url::Url;

#[cfg(any(doc, feature = "test-gateway"))]
#[cfg(doc)]
use crate::data::Did;

use super::v0alpha1::ReplicationMode;
Expand All @@ -40,10 +39,6 @@ use super::v0alpha1::ReplicationMode;
/// API. It embodies the intended usage of the REST API, which includes an
/// opening handshake (with associated key verification) and various
/// UCAN-authorized verbs over sphere data.
///
/// When built with the `test-gateway` flag, a modified Host header
/// is sent, rewriting Host to `{IDENTITY}.gateway.test`, where IDENTITY
/// is the client sphere identity with the `did:key:` prefix stripped.
pub struct Client<K, S>
where
K: KeyMaterial + Clone + 'static,
Expand All @@ -66,9 +61,6 @@ where
pub store: S,

client: reqwest::Client,

#[cfg(feature = "test-gateway")]
forced_host_header: reqwest::header::HeaderValue,
}

impl<K, S> Client<K, S>
Expand All @@ -95,22 +87,10 @@ where

let client = reqwest::Client::new();

#[cfg(feature = "test-gateway")]
let forced_host_header = create_test_header(api_base, &Did::from(sphere_identity))?;

let did_response = {
let mut url = api_base.clone();
url.set_path(&v0alpha1::Route::Did.to_string());

#[allow(unused_mut)]
let mut client = client.get(url);

#[cfg(feature = "test-gateway")]
{
client = client.header(reqwest::header::HOST, &forced_host_header);
}

client.send().await?
client.get(url).send().await?
};

match did_response.status() {
Expand All @@ -123,22 +103,18 @@ where
let mut url = api_base.clone();
url.set_path(&v0alpha1::Route::Identify.to_string());

#[allow(unused_mut)]
let (jwt, mut headers) = Self::make_bearer_token(
let (jwt, ucan_headers) = Self::make_bearer_token(
&gateway_identity,
author,
&generate_capability(sphere_identity, SphereAbility::Fetch),
&store,
)
.await?;

#[cfg(feature = "test-gateway")]
apply_test_header(&mut headers, &forced_host_header);

let identify_response: v0alpha1::IdentifyResponse = client
.get(url)
.bearer_auth(jwt)
.headers(headers)
.headers(ucan_headers)
.send()
.await?
.json()
Expand All @@ -158,8 +134,6 @@ where
author: author.clone(),
store,
client,
#[cfg(feature = "test-gateway")]
forced_host_header,
})
}

Expand Down Expand Up @@ -265,23 +239,19 @@ where

let capability = generate_capability(&self.sphere_identity, SphereAbility::Fetch);

#[allow(unused_mut)]
let (token, mut headers) = Self::make_bearer_token(
let (token, ucan_headers) = Self::make_bearer_token(
&self.session.gateway_identity,
&self.author,
&capability,
&self.store,
)
.await?;

#[cfg(feature = "test-gateway")]
apply_test_header(&mut headers, &self.forced_host_header);

let response = self
.client
.get(url)
.bearer_auth(token)
.headers(headers)
.headers(ucan_headers)
.send()
.await?;

Expand Down Expand Up @@ -330,23 +300,19 @@ where
debug!("Client fetching blocks from {}", url);

let capability = generate_capability(&self.sphere_identity, SphereAbility::Fetch);
#[allow(unused_mut)]
let (token, mut headers) = Self::make_bearer_token(
let (token, ucan_headers) = Self::make_bearer_token(
&self.session.gateway_identity,
&self.author,
&capability,
&self.store,
)
.await?;

#[cfg(feature = "test-gateway")]
apply_test_header(&mut headers, &self.forced_host_header);

let response = self
.client
.get(url)
.bearer_auth(token)
.headers(headers)
.headers(ucan_headers)
.send()
.await?;

Expand Down Expand Up @@ -414,7 +380,7 @@ where
async fn make_push_request(
&self,
url: Url,
headers: HeaderMap,
ucan_headers: HeaderMap,
token: &str,
push_body: &v0alpha2::PushBody,
) -> Result<impl Stream<Item = Result<(Cid, Vec<u8>)>> + ConditionalSend, v0alpha2::PushError>
Expand All @@ -431,12 +397,12 @@ where
use wasm_bindgen::JsValue;
use wasm_streams::ReadableStream;

let all_headers = Headers::new();
all_headers.append("Authorization", &format!("Bearer {}", token));
let headers = Headers::new();
headers.append("Authorization", &format!("Bearer {}", token));

for (name, value) in headers {
for (name, value) in ucan_headers {
if let (Some(name), Ok(value)) = (name, value.to_str()) {
all_headers.append(name.as_str(), value);
headers.append(name.as_str(), value);
}
}

Expand All @@ -449,7 +415,7 @@ where

let request = RequestBuilder::new(url.as_str())
.method(Method::PUT)
.headers(all_headers)
.headers(headers)
.body(JsValue::from(readable_stream.as_raw()))
.map_err(|error| v0alpha2::PushError::Internal(Some(error.to_string())))?;

Expand Down Expand Up @@ -486,7 +452,7 @@ where
async fn make_push_request(
&self,
url: Url,
headers: HeaderMap,
ucan_headers: HeaderMap,
token: &str,
push_body: &v0alpha2::PushBody,
) -> Result<impl Stream<Item = Result<(Cid, Vec<u8>)>> + ConditionalSend, v0alpha2::PushError>
Expand All @@ -499,7 +465,7 @@ where
.client
.put(url)
.bearer_auth(token)
.headers(headers)
.headers(ucan_headers)
.header("Content-Type", "application/octet-stream")
.body(Body::wrap_stream(stream))
.send()
Expand Down Expand Up @@ -534,20 +500,16 @@ where
push_body.sphere, url
);
let capability = generate_capability(&self.sphere_identity, SphereAbility::Push);
#[allow(unused_mut)]
let (token, mut headers) = Self::make_bearer_token(
let (token, ucan_headers) = Self::make_bearer_token(
&self.session.gateway_identity,
&self.author,
&capability,
&self.store,
)
.await?;

#[cfg(feature = "test-gateway")]
apply_test_header(&mut headers, &self.forced_host_header);

let block_stream = self
.make_push_request(url, headers, &token, push_body)
.make_push_request(url, ucan_headers, &token, push_body)
.await?;

tokio::pin!(block_stream);
Expand All @@ -567,59 +529,3 @@ where
Ok(push_response)
}
}

#[cfg(feature = "test-gateway")]
fn apply_test_header(headers: &mut HeaderMap, forced_host_header: &reqwest::header::HeaderValue) {
use reqwest::header::HOST;
_ = headers.remove(HOST);
headers.insert(HOST, forced_host_header.to_owned());
}

#[cfg(feature = "test-gateway")]
fn create_test_header(api_base: &Url, identity: &Did) -> Result<reqwest::header::HeaderValue> {
let mod_identity = identity
.as_str()
.strip_prefix("did:key:")
.ok_or_else(|| anyhow!("Could not format Host header for test-gateway."))?;
let domain = api_base
.domain()
.ok_or_else(|| anyhow!("Host header does not have domain."))?;
let port = api_base.port();

let new_host = if let Some(port) = port {
format!("{}.{}:{}", mod_identity, domain, port)
} else {
format!("{}.{}", mod_identity, domain)
};

Ok(reqwest::header::HeaderValue::from_str(&new_host)?)
}

#[cfg(all(test, feature = "test-gateway"))]
mod tests {
use super::*;
use reqwest::header::HeaderValue;

#[test]
fn it_creates_test_header_from_url() -> Result<()> {
let identity = Did::from("did:key:z6Mkuj9KHUDzGng3rKPouDgnrJJAk9DiBLRL7nWV4ULMs4E7");
let mod_id = "z6Mkuj9KHUDzGng3rKPouDgnrJJAk9DiBLRL7nWV4ULMs4E7";
let expectations = [
("http://localhost", format!("{mod_id}.localhost")),
("http://localhost:1234", format!("{mod_id}.localhost:1234")),
("http://foo.bar", format!("{mod_id}.foo.bar")),
("http://foo.bar:1234", format!("{mod_id}.foo.bar:1234")),
];

for (api_base, expected_host) in expectations {
assert_eq!(
create_test_header(&Url::parse(api_base)?, &identity)?,
HeaderValue::from_str(&expected_host)?
);
}

assert!(create_test_header(&Url::parse("http://127.0.0.1")?, &identity).is_err());
assert!(create_test_header(&Url::parse("http://127.0.0.1:1234")?, &identity).is_err());
Ok(())
}
}

0 comments on commit dcabe66

Please sign in to comment.