Repository: libsql/libsql
File: libsql-server/src/http/user/mod.rs (Rust)

Code before:
            join_set.spawn(async move {
                hyper::server::Server::builder(acceptor)
                    .serve(h2c)
                    .with_graceful_shutdown(self.shutdown.notified())
                    .await
                    .context("http server")?;
                Ok(())
            });
        }
        hrana_http_srv
    }
}

/// Axum authenticated extractor
#[tonic::async_trait]
impl<M> FromRequestParts<AppState<M>> for Authenticated
where
    M: MakeNamespace,
{
    type Rejection = Error;

    async fn from_request_parts(
        parts: &mut Parts,
        state: &AppState<M>,
    ) -> Result<Self, Self::Rejection> {
        let ns = db_factory::namespace_from_headers(
            &parts.headers,
            state.disable_default_namespace,
            state.disable_namespaces,
        )?;
        let namespace_jwt_key = state.namespaces.jwt_key(ns).await?;
        let auth_header = parts.headers.get(hyper::header::AUTHORIZATION);
        let auth = state.auth.authenticate_http(
            auth_header,
            state.disable_namespaces,
            namespace_jwt_key,
        )?;

        Ok(auth)
    }
}

impl<F: MakeNamespace> FromRef<AppState<F>> for Arc<Auth> {
    fn from_ref(input: &AppState<F>) -> Self {
        input.auth.clone()
    }
}

#[derive(Debug, Clone, Copy, Default)]
#[must_use]
pub struct Json<T>(pub T);

Review comment (refactor):
I believe we are repeating this logic now https://github.com/tursodatabase/libsql/blob/main/libsql-server/src/http/user/db_factory.rs#L30. I think I suggested we combine that so I assume there was something that didn't work when you tried that? If so I am curious what it is. I think redoing that logic/middleware extractor makes a lot of sense. This could also be a follow up item but lets track that.

Code after:
            join_set.spawn(async move {
                hyper::server::Server::builder(acceptor)
                    .serve(h2c)
                    .with_graceful_shutdown(self.shutdown.notified())
                    .await
                    .context("http server")?;
                Ok(())
            });
        }
        hrana_http_srv
    }
}

/// Axum authenticated extractor
#[tonic::async_trait]
impl<M> FromRequestParts<AppState<M>> for Authenticated
where
    M: MakeNamespace,
{
    type Rejection = Error;

    async fn from_request_parts(
        parts: &mut Parts,
        state: &AppState<M>,
    ) -> Result<Self, Self::Rejection> {
        let ns = db_factory::namespace_from_headers(
            &parts.headers,
            state.disable_default_namespace,
            state.disable_namespaces,
        )?;
        let namespace_jwt_key = state.namespaces.with(ns, |ns| ns.jwt_key()).await??;
        let auth_header = parts.headers.get(hyper::header::AUTHORIZATION);
        let auth = state.auth.authenticate_http(
            auth_header,
            state.disable_namespaces,
            namespace_jwt_key,
        )?;

        Ok(auth)
    }
}

impl<F: MakeNamespace> FromRef<AppState<F>> for Arc<Auth> {
    fn from_ref(input: &AppState<F>) -> Self {
        input.auth.clone()
    }
}

#[derive(Debug, Clone, Copy, Default)]
#[must_use]
pub struct Json<T>(pub T);