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(-)
@@ -210,6 +210,7 @@
version = "0.1.0"
dependencies = [
"axum",
"futures",
"tokio",
"tower",
"tower-http",
@@ -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"] }
@@ -1,2 +1,0 @@
target/
Cargo.lock
@@ -1,9 +1,0 @@
[package]
name = "test-using-chartered"
version = "0.1.0"
edition = "2018"
[dependencies]
charteredtest = { version = "1", registry = "chartered" }
@@ -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 {
@@ -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!"
}
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();
}
@@ -1,2 +1,0 @@
[registries]
chartered = { index = "ssh://127.0.0.1:2233/" }
@@ -1,7 +1,0 @@
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}
@@ -1,0 +1,1 @@
pub mod cargo_api;
@@ -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 {
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)
})
}
}
@@ -1,0 +1,1 @@
pub mod auth;
@@ -1,0 +1,3 @@
pub async fn handle() -> &'static str {
"download"
}
@@ -1,0 +1,3 @@
mod download;
pub use download::handle as download;