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 librqbit_core::torrent_metainfo::TorrentMetaV1Info;
|
||||
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 tracing::warn;
|
||||
|
||||
|
|
@ -239,6 +242,11 @@ impl Api {
|
|||
let mgr = self.mgr_handle(idx)?;
|
||||
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)]
|
||||
|
|
|
|||
|
|
@ -8,9 +8,11 @@ use futures::{FutureExt, TryStreamExt};
|
|||
use itertools::Itertools;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::io::SeekFrom;
|
||||
use std::net::SocketAddr;
|
||||
use std::str::FromStr;
|
||||
use std::time::Duration;
|
||||
use tokio::io::AsyncSeekExt;
|
||||
use tracing::{debug, info};
|
||||
|
||||
use axum::Router;
|
||||
|
|
@ -154,6 +156,31 @@ impl HttpApi {
|
|||
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(
|
||||
State(state): State<ApiState>,
|
||||
Path(idx): Path<usize>,
|
||||
|
|
@ -223,7 +250,8 @@ impl HttpApi {
|
|||
.route("/torrents/:id/haves", get(torrent_haves))
|
||||
.route("/torrents/:id/stats", get(torrent_stats_v0))
|
||||
.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 {
|
||||
app = app
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue