🏡 index : ~doyle/chartered.git

author Jordan Doyle <jordan@doyle.la> 2021-08-31 20:04:35.0 +01:00:00
committer Jordan Doyle <jordan@doyle.la> 2021-08-31 20:06:22.0 +01:00:00
commit
8a06f53ec0cb3019b9000490ac8598b5ea84f267 [patch]
tree
0226eef4d88b58b485a468811fa39cef0b86d318
parent
2120f790bf61f74180548ce313a033b916c559e7
download
8a06f53ec0cb3019b9000490ac8598b5ea84f267.tar.gz

Define cargo API routes in chartered-web



Diff

 Cargo.lock                                        |  1 +
 chartered-web/Cargo.toml                          |  1 +
 test-using-chartered/.gitignore                   |  2 --
 test-using-chartered/Cargo.toml                   |  9 ---------
 chartered-git/src/main.rs                         | 24 +++++++++++-------------
 chartered-web/src/main.rs                         | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 test-using-chartered/.cargo/config.toml           |  2 --
 test-using-chartered/src/lib.rs                   |  7 -------
 chartered-web/src/endpoints/mod.rs                |  1 +
 chartered-web/src/middleware/auth.rs              | 43 +++++++++++++++++++++++++++++++++++++++++++
 chartered-web/src/middleware/mod.rs               |  1 +
 chartered-web/src/endpoints/cargo_api/download.rs |  3 +++
 chartered-web/src/endpoints/cargo_api/mod.rs      |  3 +++
 13 files changed, 124 insertions(+), 35 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index ddfce59..80939a3 100644
--- a/Cargo.lock
+++ a/Cargo.lock
@@ -210,6 +210,7 @@
version = "0.1.0"
dependencies = [
 "axum",
 "futures",
 "tokio",
 "tower",
 "tower-http",
diff --git a/chartered-web/Cargo.toml b/chartered-web/Cargo.toml
index e50ae48..d1ac7f5 100644
--- a/chartered-web/Cargo.toml
+++ a/chartered-web/Cargo.toml
@@ -7,6 +7,7 @@

[dependencies]
axum = "0.2"
futures = "0.3"
tokio = { version = "1", features = ["full"] }
tower = { version = "0.4", features = ["util", "filter"] }
tower-http = { version = "0.1", features = ["trace"] }
diff --git a/test-using-chartered/.gitignore b/test-using-chartered/.gitignore
deleted file mode 100644
index 2c96eb1..0000000 100644
--- a/test-using-chartered/.gitignore
+++ /dev/null
@@ -1,2 +1,0 @@
target/
Cargo.lock
diff --git a/test-using-chartered/Cargo.toml b/test-using-chartered/Cargo.toml
deleted file mode 100644
index 471bf5c..0000000 100644
--- a/test-using-chartered/Cargo.toml
+++ /dev/null
@@ -1,9 +1,0 @@
[package]
name = "test-using-chartered"
version = "0.1.0"
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
charteredtest = { version = "1", registry = "chartered" }
diff --git a/chartered-git/src/main.rs b/chartered-git/src/main.rs
index 92529cc..fb358e6 100644
--- a/chartered-git/src/main.rs
+++ a/chartered-git/src/main.rs
@@ -177,21 +177,17 @@
            }"#,
            );

            let ch_ar_tree = PackFileEntry::Tree(vec![
                TreeItem {
                    kind: TreeItemKind::File,
                    name: "charteredtest",
                    hash: test_crate_file.hash()?,
                }
            ]);
            let ch_ar_tree = PackFileEntry::Tree(vec![TreeItem {
                kind: TreeItemKind::File,
                name: "charteredtest",
                hash: test_crate_file.hash()?,
            }]);

            let ch_tree = PackFileEntry::Tree(vec![
                TreeItem {
                    kind: TreeItemKind::Directory,
                    name: "ar",
                    hash: ch_ar_tree.hash()?,
                }
            ]);
            let ch_tree = PackFileEntry::Tree(vec![TreeItem {
                kind: TreeItemKind::Directory,
                name: "ar",
                hash: ch_ar_tree.hash()?,
            }]);

            let root_tree = PackFileEntry::Tree(vec![
                TreeItem {
diff --git a/chartered-web/src/main.rs b/chartered-web/src/main.rs
index 7e3d561..ad7525f 100644
--- a/chartered-web/src/main.rs
+++ a/chartered-web/src/main.rs
@@ -1,4 +1,64 @@
mod endpoints;
mod middleware;

use axum::{
    handler::{delete, get, put},
    Router,
};
use tower::{filter::AsyncFilterLayer, ServiceBuilder};

async fn hello_world() -> &'static str {
    "hello, world!"
}

// there's some sort of issue with monomorphization of axum routes
// which causes compile times to increase exponentially with every
// new route, the workaround is to box the router down to a
// dynamically dispatched version with every new route.
macro_rules! axum_box_after_every_route {
    (Router::new()$(.route($path:expr, $svc:expr$(,)?))*) => {
        Router::new()
            $(
                .route($path, $svc)
                .boxed()
            )*
    };
}

#[tokio::main]
async fn main() {
    println!("Hello, world!");
    let api_authenticated = axum_box_after_every_route!(Router::new()
        .route("/crates/new", put(hello_world))
        .route("/crates/search", get(hello_world))
        .route("/crates/:crate/owners", get(hello_world))
        .route("/crates/:crate/owners", put(hello_world))
        .route("/crates/:crate/owners", delete(hello_world))
        .route("/crates/:crate/:version/yank", delete(hello_world))
        .route("/crates/:crate/:version/unyank", put(hello_world))
        .route(
            "/crates/:crate/:version/download",
            get(endpoints::cargo_api::download),
        ))
    .layer(
        ServiceBuilder::new()
            .layer_fn(middleware::auth::AuthMiddleware)
            .into_inner(),
    );

    let middleware_stack = ServiceBuilder::new()
        .layer(AsyncFilterLayer::new(|req| async {
            eprintln!("{:#?}", req);
            Ok::<_, std::convert::Infallible>(req)
        }))
        .into_inner();

    let app = Router::new()
        .route("/", get(hello_world))
        .nest("/a/:key/api/v1", api_authenticated)
        .layer(middleware_stack);

    axum::Server::bind(&"0.0.0.0:8888".parse().unwrap())
        .serve(app.into_make_service())
        .await
        .unwrap();
}
diff --git a/test-using-chartered/.cargo/config.toml b/test-using-chartered/.cargo/config.toml
deleted file mode 100644
index 37f88f8..0000000 100644
--- a/test-using-chartered/.cargo/config.toml
+++ /dev/null
@@ -1,2 +1,0 @@
[registries]
chartered = { index = "ssh://127.0.0.1:2233/" }
diff --git a/test-using-chartered/src/lib.rs b/test-using-chartered/src/lib.rs
deleted file mode 100644
index 31e1bb2..0000000 100644
--- a/test-using-chartered/src/lib.rs
+++ /dev/null
@@ -1,7 +1,0 @@
#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
        assert_eq!(2 + 2, 4);
    }
}
diff --git a/chartered-web/src/endpoints/mod.rs b/chartered-web/src/endpoints/mod.rs
new file mode 100644
index 0000000..168c1af 100644
--- /dev/null
+++ a/chartered-web/src/endpoints/mod.rs
@@ -1,0 +1,1 @@
pub mod cargo_api;
diff --git a/chartered-web/src/middleware/auth.rs b/chartered-web/src/middleware/auth.rs
new file mode 100644
index 0000000..a6a6154 100644
--- /dev/null
+++ a/chartered-web/src/middleware/auth.rs
@@ -1,0 +1,43 @@
use axum::http::{Request, Response, StatusCode};
use futures::future::BoxFuture;
use std::task::{Context, Poll};
use tower::Service;

#[derive(Clone)]
pub struct AuthMiddleware<S>(pub S);

impl<S, ReqBody, ResBody> Service<Request<ReqBody>> for AuthMiddleware<S>
where
    S: Service<Request<ReqBody>, Response = Response<ResBody>> + Clone + Send + 'static,
    S::Future: Send + 'static,
    ReqBody: Send + 'static,
    ResBody: Default + Send + 'static,
{
    type Response = S::Response;
    type Error = S::Error;
    type Future = BoxFuture<'static, Result<Self::Response, Self::Error>>;

    fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
        self.0.poll_ready(cx)
    }

    fn call(&mut self, req: Request<ReqBody>) -> Self::Future {
        // best practice is to clone the inner service like this
        // see https://github.com/tower-rs/tower/issues/547 for details
        let clone = self.0.clone();
        let mut inner = std::mem::replace(&mut self.0, clone);

        Box::pin(async move {
            if true {
                return Ok(Response::builder()
                    .status(StatusCode::UNAUTHORIZED)
                    .body(ResBody::default())
                    .unwrap());
            }

            let res: Response<ResBody> = inner.call(req).await?;

            Ok(res)
        })
    }
}
diff --git a/chartered-web/src/middleware/mod.rs b/chartered-web/src/middleware/mod.rs
new file mode 100644
index 0000000..0e4a05d 100644
--- /dev/null
+++ a/chartered-web/src/middleware/mod.rs
@@ -1,0 +1,1 @@
pub mod auth;
diff --git a/chartered-web/src/endpoints/cargo_api/download.rs b/chartered-web/src/endpoints/cargo_api/download.rs
new file mode 100644
index 0000000..a03b66a 100644
--- /dev/null
+++ a/chartered-web/src/endpoints/cargo_api/download.rs
@@ -1,0 +1,3 @@
pub async fn handle() -> &'static str {
    "download"
}
diff --git a/chartered-web/src/endpoints/cargo_api/mod.rs b/chartered-web/src/endpoints/cargo_api/mod.rs
new file mode 100644
index 0000000..4ca25db 100644
--- /dev/null
+++ a/chartered-web/src/endpoints/cargo_api/mod.rs
@@ -1,0 +1,3 @@
mod download;

pub use download::handle as download;