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

Commit

Permalink
feat: add Content-Length headers when writing to a sphere.
Browse files Browse the repository at this point in the history
  • Loading branch information
jsantell authored and cdata committed Jan 16, 2024
1 parent 5f67c26 commit 0e4fdb0
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 4 deletions.
13 changes: 12 additions & 1 deletion rust/noosphere-core/src/context/content/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,18 @@ where
let body_cid =
BodyChunkIpld::store_bytes(&bytes, self.sphere_context_mut().await?.db_mut()).await?;

self.link(slug, content_type, &body_cid, additional_headers)
let header = (
Header::ContentLength.to_string(),
format!("{}", bytes.len()),
);
let additional_headers = if let Some(mut headers) = additional_headers {
headers.push(header);
headers
} else {
vec![header]
};

self.link(slug, content_type, &body_cid, Some(additional_headers))
.await
}

Expand Down
66 changes: 63 additions & 3 deletions rust/noosphere-core/src/context/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,22 +256,82 @@ mod tests {
use crate::{
authority::{generate_capability, generate_ed25519_key, Access, SphereAbility},
context::{
HasMutableSphereContext, HasSphereContext, SphereContentWrite, SpherePetnameWrite,
AsyncFileBody, HasMutableSphereContext, HasSphereContext, SphereContentWrite,
SpherePetnameWrite,
},
data::{ContentType, LinkRecord, LINK_RECORD_FACT_NAME},
data::{ContentType, Header, LinkRecord, LINK_RECORD_FACT_NAME},
helpers::{make_valid_link_record, simulated_sphere_context},
tracing::initialize_tracing,
view::Sphere,
};

use noosphere_storage::{MemoryStorage, SphereDb};
use noosphere_storage::{MemoryStorage, SphereDb, Storage};
use serde_json::json;
use ucan::{builder::UcanBuilder, crypto::KeyMaterial, store::UcanJwtStore};

#[cfg(target_arch = "wasm32")]
use wasm_bindgen_test::wasm_bindgen_test;

#[cfg(target_arch = "wasm32")]
wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);

#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
#[cfg_attr(not(target_arch = "wasm32"), tokio::test)]
async fn it_sets_content_length_and_type_on_write() -> Result<()> {
initialize_tracing(None);

let (mut sphere_context, _) = simulated_sphere_context(Access::ReadWrite, None).await?;

check_headers(
&mut sphere_context,
"note",
ContentType::Text,
"hello".as_ref(),
"5",
)
.await?;

check_headers(
&mut sphere_context,
"note",
ContentType::Json,
json!({"foo":true}).to_string().as_ref(),
"12",
)
.await?;

async fn check_headers<C, S, F>(
sphere_context: &mut C,
slug: &str,
content_type: ContentType,
content: F,
expected_length: &str,
) -> Result<()>
where
C: HasMutableSphereContext<S>,
S: Storage + 'static,
F: AsyncFileBody,
{
let db = sphere_context.sphere_context().await?.db().clone();
let link = sphere_context
.write(slug, &content_type, content, None)
.await?;
let memo = link.load_from(&db).await?;
assert_eq!(
memo.headers,
vec![
(
Header::ContentLength.to_string(),
expected_length.to_owned()
),
(Header::ContentType.to_string(), content_type.to_string())
]
);
Ok(())
}
Ok(())
}

#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
#[cfg_attr(not(target_arch = "wasm32"), tokio::test)]
async fn it_validates_slug_names_when_writing() -> Result<()> {
Expand Down
4 changes: 4 additions & 0 deletions rust/noosphere-core/src/data/headers/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ use std::{convert::Infallible, fmt::Display, ops::Deref, str::FromStr};

/// Well-known headers in the Noosphere
pub enum Header {
/// The content length (in bytes) of associated binary data
ContentLength,
/// Content-type, for mimes
ContentType,
/// A proof, typically a UCAN JWT
Expand Down Expand Up @@ -34,6 +36,7 @@ impl FromStr for Header {

fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(match s.to_lowercase().as_str() {
"content-length" => Header::ContentLength,
"content-type" => Header::ContentType,
"file-extension" => Header::FileExtension,
"proof" => Header::Proof,
Expand All @@ -52,6 +55,7 @@ impl Deref for Header {

fn deref(&self) -> &Self::Target {
match self {
Header::ContentLength => "Content-Length",
Header::ContentType => "Content-Type",
Header::Proof => "Proof",
Header::Author => "Author",
Expand Down

0 comments on commit 0e4fdb0

Please sign in to comment.