Should be ready to test
This commit is contained in:
parent
d1c6a5b584
commit
eadb8872d9
2 changed files with 38 additions and 2 deletions
|
|
@ -7,7 +7,10 @@ use futures::Stream;
|
||||||
use http::StatusCode;
|
use http::StatusCode;
|
||||||
use librqbit_core::torrent_metainfo::TorrentMetaV1Info;
|
use librqbit_core::torrent_metainfo::TorrentMetaV1Info;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tokio::sync::mpsc::UnboundedSender;
|
use tokio::{
|
||||||
|
io::{AsyncRead, AsyncSeek},
|
||||||
|
sync::mpsc::UnboundedSender,
|
||||||
|
};
|
||||||
use tokio_stream::wrappers::{errors::BroadcastStreamRecvError, BroadcastStream};
|
use tokio_stream::wrappers::{errors::BroadcastStreamRecvError, BroadcastStream};
|
||||||
use tracing::warn;
|
use tracing::warn;
|
||||||
|
|
||||||
|
|
@ -239,6 +242,11 @@ impl Api {
|
||||||
let mgr = self.mgr_handle(idx)?;
|
let mgr = self.mgr_handle(idx)?;
|
||||||
Ok(mgr.with_chunk_tracker(|chunks| format!("{:?}", chunks.get_have_pieces()))?)
|
Ok(mgr.with_chunk_tracker(|chunks| format!("{:?}", chunks.get_have_pieces()))?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn api_stream(&self, idx: TorrentId, file_id: usize) -> Result<impl AsyncRead + AsyncSeek> {
|
||||||
|
let mgr = self.mgr_handle(idx)?;
|
||||||
|
Ok(mgr.stream(file_id)?)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,11 @@ use futures::{FutureExt, TryStreamExt};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::io::SeekFrom;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
use tokio::io::AsyncSeekExt;
|
||||||
use tracing::{debug, info};
|
use tracing::{debug, info};
|
||||||
|
|
||||||
use axum::Router;
|
use axum::Router;
|
||||||
|
|
@ -154,6 +156,31 @@ impl HttpApi {
|
||||||
state.api_peer_stats(idx, filter).map(axum::Json)
|
state.api_peer_stats(idx, filter).map(axum::Json)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn torrent_stream_file(
|
||||||
|
State(state): State<ApiState>,
|
||||||
|
Path((idx, file_id)): Path<(usize, usize)>,
|
||||||
|
headers: http::HeaderMap,
|
||||||
|
) -> Result<impl IntoResponse> {
|
||||||
|
let mut stream = state.api_stream(idx, file_id)?;
|
||||||
|
if let Some(range) = headers.get(http::header::RANGE) {
|
||||||
|
let offset: Option<u64> = range
|
||||||
|
.to_str()
|
||||||
|
.ok()
|
||||||
|
.and_then(|s| s.strip_prefix("bytes="))
|
||||||
|
.and_then(|s| s.strip_suffix('-'))
|
||||||
|
.and_then(|s| s.parse().ok());
|
||||||
|
if let Some(offset) = offset {
|
||||||
|
stream
|
||||||
|
.seek(SeekFrom::Start(offset))
|
||||||
|
.await
|
||||||
|
.context("error seeking")?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let s = tokio_util::io::ReaderStream::new(stream);
|
||||||
|
Ok(axum::body::Body::from_stream(s))
|
||||||
|
}
|
||||||
|
|
||||||
async fn torrent_action_pause(
|
async fn torrent_action_pause(
|
||||||
State(state): State<ApiState>,
|
State(state): State<ApiState>,
|
||||||
Path(idx): Path<usize>,
|
Path(idx): Path<usize>,
|
||||||
|
|
@ -223,7 +250,8 @@ impl HttpApi {
|
||||||
.route("/torrents/:id/haves", get(torrent_haves))
|
.route("/torrents/:id/haves", get(torrent_haves))
|
||||||
.route("/torrents/:id/stats", get(torrent_stats_v0))
|
.route("/torrents/:id/stats", get(torrent_stats_v0))
|
||||||
.route("/torrents/:id/stats/v1", get(torrent_stats_v1))
|
.route("/torrents/:id/stats/v1", get(torrent_stats_v1))
|
||||||
.route("/torrents/:id/peer_stats", get(peer_stats));
|
.route("/torrents/:id/peer_stats", get(peer_stats))
|
||||||
|
.route("/torrents/:id/stream/:file_id", get(torrent_stream_file));
|
||||||
|
|
||||||
if !self.opts.read_only {
|
if !self.opts.read_only {
|
||||||
app = app
|
app = app
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue