75 lines
2.0 KiB
Rust
75 lines
2.0 KiB
Rust
use std::convert::Infallible;
|
|
|
|
use axum::{
|
|
extract::{Path, State},
|
|
response::{
|
|
sse::{Event, KeepAlive},
|
|
IntoResponse, Sse,
|
|
},
|
|
};
|
|
use bollard::container::LogsOptions;
|
|
use futures_util::StreamExt;
|
|
use serde_json::json;
|
|
|
|
use crate::{http::accept::ExtractAccept, AppState};
|
|
|
|
pub(super) async fn get(
|
|
Path(container_name): Path<String>,
|
|
State(state): State<AppState>,
|
|
ExtractAccept(accept): ExtractAccept,
|
|
) -> impl IntoResponse {
|
|
match accept.to_str() {
|
|
Ok("text/event-stream") => get_log_stream(container_name, state).await.into_response(),
|
|
_ => get_log_string(container_name, state).await.into_response(),
|
|
}
|
|
}
|
|
|
|
async fn get_log_string(container_name: String, state: AppState) -> impl IntoResponse {
|
|
state
|
|
.docker
|
|
.logs(
|
|
&container_name,
|
|
Some(LogsOptions::<String> {
|
|
follow: false,
|
|
stdout: true,
|
|
stderr: true,
|
|
timestamps: true,
|
|
..Default::default()
|
|
}),
|
|
)
|
|
.map(|ev| match ev {
|
|
Ok(output) => output.to_string(),
|
|
Err(error) => error.to_string(),
|
|
})
|
|
.collect::<Vec<_>>()
|
|
.await
|
|
.join("\n")
|
|
}
|
|
|
|
async fn get_log_stream(container_name: String, state: AppState) -> impl IntoResponse {
|
|
let stream = state
|
|
.docker
|
|
.logs(
|
|
&container_name,
|
|
Some(LogsOptions::<String> {
|
|
follow: true,
|
|
stdout: true,
|
|
stderr: true,
|
|
timestamps: true,
|
|
..Default::default()
|
|
}),
|
|
)
|
|
.map(|msg| match msg {
|
|
Ok(output) => Ok::<_, Infallible>(
|
|
Event::default()
|
|
.json_data(json!({ "lines": output.to_string() }))
|
|
.unwrap(),
|
|
),
|
|
Err(error) => Ok(Event::default()
|
|
.json_data(json!({ "error": error.to_string() }))
|
|
.unwrap()),
|
|
});
|
|
|
|
Sse::new(stream).keep_alive(KeepAlive::default())
|
|
}
|