Merge pull request #162 from izderadicka/add_content_type_to_stream
Add content type to streams
This commit is contained in:
commit
c86e663f24
6 changed files with 61 additions and 7 deletions
20
Cargo.lock
generated
20
Cargo.lock
generated
|
|
@ -1317,6 +1317,7 @@ dependencies = [
|
||||||
"librqbit-upnp",
|
"librqbit-upnp",
|
||||||
"lru",
|
"lru",
|
||||||
"memmap2",
|
"memmap2",
|
||||||
|
"mime_guess",
|
||||||
"openssl",
|
"openssl",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"rand",
|
"rand",
|
||||||
|
|
@ -1539,6 +1540,16 @@ version = "0.3.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
|
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mime_guess"
|
||||||
|
version = "2.0.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e"
|
||||||
|
dependencies = [
|
||||||
|
"mime",
|
||||||
|
"unicase",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "minimal-lexical"
|
name = "minimal-lexical"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
|
|
@ -2822,6 +2833,15 @@ version = "1.17.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
|
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicase"
|
||||||
|
version = "2.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89"
|
||||||
|
dependencies = [
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-bidi"
|
name = "unicode-bidi"
|
||||||
version = "0.3.15"
|
version = "0.3.15"
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,7 @@ rlimit = "0.10.1"
|
||||||
async-stream = "0.3.5"
|
async-stream = "0.3.5"
|
||||||
memmap2 = { version = "0.9.4" }
|
memmap2 = { version = "0.9.4" }
|
||||||
lru = { version = "0.12.3", optional = true }
|
lru = { version = "0.12.3", optional = true }
|
||||||
|
mime_guess = { version = "2.0.5", default-features = false}
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
futures = { version = "0.3" }
|
futures = { version = "0.3" }
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,12 @@ impl Api {
|
||||||
make_torrent_details(&info_hash, &handle.info().info, only_files.as_deref())
|
make_torrent_details(&info_hash, &handle.info().info, only_files.as_deref())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn torrent_file_mime_type(&self, idx: TorrentId, file_idx: usize) -> Result<&'static str> {
|
||||||
|
let handle = self.mgr_handle(idx)?;
|
||||||
|
let info = &handle.info().info;
|
||||||
|
torrent_file_mime_type(info, file_idx)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn api_peer_stats(
|
pub fn api_peer_stats(
|
||||||
&self,
|
&self,
|
||||||
idx: TorrentId,
|
idx: TorrentId,
|
||||||
|
|
@ -320,3 +326,23 @@ fn make_torrent_details(
|
||||||
files,
|
files,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn torrent_file_mime_type(
|
||||||
|
info: &TorrentMetaV1Info<ByteBufOwned>,
|
||||||
|
file_idx: usize,
|
||||||
|
) -> Result<&'static str> {
|
||||||
|
info.iter_filenames_and_lengths()?
|
||||||
|
.nth(file_idx)
|
||||||
|
.and_then(|(f, _)| {
|
||||||
|
f.iter_components()
|
||||||
|
.last()
|
||||||
|
.and_then(|r| r.ok())
|
||||||
|
.and_then(|s| mime_guess::from_path(s).first_raw())
|
||||||
|
})
|
||||||
|
.ok_or_else(|| {
|
||||||
|
ApiError::new_from_text(
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
"cannot determine mime type for file",
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -167,6 +167,13 @@ impl HttpApi {
|
||||||
let mut output_headers = HeaderMap::new();
|
let mut output_headers = HeaderMap::new();
|
||||||
output_headers.insert("Accept-Ranges", HeaderValue::from_static("bytes"));
|
output_headers.insert("Accept-Ranges", HeaderValue::from_static("bytes"));
|
||||||
|
|
||||||
|
if let Ok(mime) = state.torrent_file_mime_type(idx, file_id) {
|
||||||
|
output_headers.insert(
|
||||||
|
http::header::CONTENT_TYPE,
|
||||||
|
HeaderValue::from_str(mime).context("bug - invalid MIME")?,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let range_header = headers.get(http::header::RANGE);
|
let range_header = headers.get(http::header::RANGE);
|
||||||
trace!(torrent_id=idx, file_id=file_id, range=?range_header, "request for HTTP stream");
|
trace!(torrent_id=idx, file_id=file_id, range=?range_header, "request for HTTP stream");
|
||||||
|
|
||||||
|
|
@ -199,12 +206,12 @@ impl HttpApi {
|
||||||
))
|
))
|
||||||
.context("bug")?,
|
.context("bug")?,
|
||||||
);
|
);
|
||||||
} else {
|
|
||||||
output_headers.insert(
|
|
||||||
http::header::CONTENT_LENGTH,
|
|
||||||
HeaderValue::from_str(&format!("{}", stream.len())).context("bug")?,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
output_headers.insert(
|
||||||
|
http::header::CONTENT_LENGTH,
|
||||||
|
HeaderValue::from_str(&format!("{}", stream.len())).context("bug")?,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let s = tokio_util::io::ReaderStream::new(stream);
|
let s = tokio_util::io::ReaderStream::new(stream);
|
||||||
|
|
|
||||||
|
|
@ -158,8 +158,7 @@ const FileTreeComponent: React.FC<{
|
||||||
const fileLink = (file: TorrentFileForCheckbox) => {
|
const fileLink = (file: TorrentFileForCheckbox) => {
|
||||||
if (
|
if (
|
||||||
allowStream &&
|
allowStream &&
|
||||||
torrentId != null &&
|
torrentId != null
|
||||||
/\.(mp4|mkv|avi)$/.test(file.filename)
|
|
||||||
) {
|
) {
|
||||||
return API.getTorrentStreamUrl(torrentId, file.id, file.filename);
|
return API.getTorrentStreamUrl(torrentId, file.id, file.filename);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ export const FormCheckbox: React.FC<{
|
||||||
{labelLink ? (
|
{labelLink ? (
|
||||||
<a
|
<a
|
||||||
href={labelLink}
|
href={labelLink}
|
||||||
|
target="_blank"
|
||||||
className="text-blue-600 dark:text-blue-500 hover:underline"
|
className="text-blue-600 dark:text-blue-500 hover:underline"
|
||||||
>
|
>
|
||||||
{label}
|
{label}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue