Merge pull request #162 from izderadicka/add_content_type_to_stream

Add content type to streams
This commit is contained in:
Igor Katson 2024-08-02 12:56:13 +01:00 committed by GitHub
commit c86e663f24
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 61 additions and 7 deletions

20
Cargo.lock generated
View file

@ -1317,6 +1317,7 @@ dependencies = [
"librqbit-upnp",
"lru",
"memmap2",
"mime_guess",
"openssl",
"parking_lot",
"rand",
@ -1539,6 +1540,16 @@ version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
name = "minimal-lexical"
version = "0.2.1"
@ -2822,6 +2833,15 @@ version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
name = "unicode-bidi"
version = "0.3.15"

View file

@ -74,6 +74,7 @@ rlimit = "0.10.1"
async-stream = "0.3.5"
memmap2 = { version = "0.9.4" }
lru = { version = "0.12.3", optional = true }
mime_guess = { version = "2.0.5", default-features = false}
[dev-dependencies]
futures = { version = "0.3" }

View file

@ -78,6 +78,12 @@ impl Api {
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(
&self,
idx: TorrentId,
@ -320,3 +326,23 @@ fn make_torrent_details(
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",
)
})
}

View file

@ -167,6 +167,13 @@ impl HttpApi {
let mut output_headers = HeaderMap::new();
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);
trace!(torrent_id=idx, file_id=file_id, range=?range_header, "request for HTTP stream");
@ -199,12 +206,12 @@ impl HttpApi {
))
.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);

View file

@ -158,8 +158,7 @@ const FileTreeComponent: React.FC<{
const fileLink = (file: TorrentFileForCheckbox) => {
if (
allowStream &&
torrentId != null &&
/\.(mp4|mkv|avi)$/.test(file.filename)
torrentId != null
) {
return API.getTorrentStreamUrl(torrentId, file.id, file.filename);
}

View file

@ -39,6 +39,7 @@ export const FormCheckbox: React.FC<{
{labelLink ? (
<a
href={labelLink}
target="_blank"
className="text-blue-600 dark:text-blue-500 hover:underline"
>
{label}