1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
mod endpoints;
use hyper::body::Buf;
pub struct WebService {
backend: tokio::sync::mpsc::Sender<cargolifter_core::BackendCommand>,
storage: tokio::sync::mpsc::Sender<cargolifter_core::StorageCommand>,
config: cargolifter_core::config::WebServiceConfig,
}
pub struct RequestExtractor(cargolifter_core::models::PublishRequest);
#[axum::async_trait]
impl axum::extract::FromRequest for RequestExtractor {
type Rejection = axum::http::StatusCode;
async fn from_request(req: &mut axum::extract::RequestParts) -> Result<Self, Self::Rejection> {
let mut data = hyper::body::to_bytes(req.body_mut().unwrap())
.await
.unwrap();
let json_length = data.get_u32_le() as usize;
let json_data = &data[0..json_length].to_vec();
data.advance(json_length);
let data_length = data.get_u32_le() as usize;
Ok(Self {
0: cargolifter_core::models::PublishRequest {
meta: serde_json::from_slice(json_data).unwrap(),
data: data[0..data_length].to_vec(),
},
})
}
}
impl WebService {
pub fn new(
backend: tokio::sync::mpsc::Sender<cargolifter_core::BackendCommand>,
storage: tokio::sync::mpsc::Sender<cargolifter_core::StorageCommand>,
config: cargolifter_core::config::WebServiceConfig,
) -> Self {
Self {
backend,
storage,
config,
}
}
pub async fn run(&self) {
let host = format!("0.0.0.0:{}", self.config.port);
tracing::info!("starting web service at: {}", host);
let app = axum::Router::new()
.route(
"/api/v1/crates/:crate_name/:crate_version/download",
axum::handler::get(endpoints::download),
)
.route("/api/v1/crates/new", axum::handler::put(endpoints::publish))
.route(
"/api/v1/crates/:name/:version/yank",
axum::handler::delete(endpoints::yank),
)
.route(
"/api/v1/crates/:name/:version/unyank",
axum::handler::put(endpoints::unyank),
)
.layer(axum::AddExtensionLayer::new(self.backend.clone()))
.layer(axum::AddExtensionLayer::new(self.storage.clone()));
axum::Server::bind(&host.parse().unwrap())
.serve(app.into_make_service())
.await
.unwrap();
}
}