solid-pod-rs-server 0.5.0-alpha.21

Drop-in Solid Pod server binary. Wraps solid-pod-rs with actix-web and a JSS-compatible layered config loader.
Documentation
use async_trait::async_trait;
use bytes::Bytes;
use solid_pod_rs::{
    storage::{memory::MemoryBackend, ResourceMeta, Storage, StorageEvent},
    PodError,
};
use solid_pod_rs_server::{build_app, AppState};
use std::sync::Arc;

struct FailedCanonicalRead(MemoryBackend);

#[async_trait]
impl Storage for FailedCanonicalRead {
    async fn get(&self, path: &str) -> Result<(Bytes, ResourceMeta), PodError> {
        if path == "/.well-known/webledgers/state.json" {
            return Err(PodError::Backend(
                "injected unavailable canonical state".into(),
            ));
        }
        self.0.get(path).await
    }
    async fn put(&self, path: &str, body: Bytes, ct: &str) -> Result<ResourceMeta, PodError> {
        self.0.put(path, body, ct).await
    }
    async fn delete(&self, path: &str) -> Result<(), PodError> {
        self.0.delete(path).await
    }
    async fn list(&self, path: &str) -> Result<Vec<String>, PodError> {
        self.0.list(path).await
    }
    async fn head(&self, path: &str) -> Result<ResourceMeta, PodError> {
        self.0.head(path).await
    }
    async fn exists(&self, path: &str) -> Result<bool, PodError> {
        self.0.exists(path).await
    }
    async fn watch(
        &self,
        path: &str,
    ) -> Result<tokio::sync::mpsc::Receiver<StorageEvent>, PodError> {
        self.0.watch(path).await
    }
}

#[actix_web::test]
async fn unavailable_canonical_state_does_not_become_an_empty_legacy_book() {
    let app = actix_web::test::init_service(build_app(AppState::new(Arc::new(
        FailedCanonicalRead(MemoryBackend::new()),
    ))))
    .await;
    let rsp = actix_web::test::call_service(
        &app,
        actix_web::test::TestRequest::get()
            .uri("/pay/.offers")
            .to_request(),
    )
    .await;
    assert_eq!(
        rsp.status().as_u16(),
        500,
        "failed canonical read must not return stale or empty offers"
    );
    let app =
        actix_web::test::init_service(build_app(AppState::new(Arc::new(MemoryBackend::new()))))
            .await;
    let rsp = actix_web::test::call_service(
        &app,
        actix_web::test::TestRequest::get()
            .uri("/pay/.offers")
            .to_request(),
    )
    .await;
    assert_eq!(
        rsp.status().as_u16(),
        200,
        "a genuinely absent canonical state may bootstrap legacy state"
    );
}