read_url/http/
url.rs

1use super::{
2    super::{context::*, url::*, util::*},
3    http_url::*,
4};
5
6use relative_path::*;
7
8impl URL for HttpUrl {
9    fn context(&self) -> &UrlContext {
10        &*self.context
11    }
12
13    fn query(&self) -> Option<UrlQuery> {
14        url_query(&self.url)
15    }
16
17    fn fragment(&self) -> Option<String> {
18        url_fragment(&self.url)
19    }
20
21    fn format(&self) -> Option<String> {
22        // TODO: from MIME type?
23        get_format_from_path(self.url.path())
24    }
25
26    fn base(&self) -> Option<UrlRef> {
27        get_relative_path_parent(self.url.path()).map(|path| self.new_with(path.as_str()).into())
28    }
29
30    fn relative(&self, path: &str) -> UrlRef {
31        self.new_with(RelativePath::new(self.url.path()).join(path).as_str()).into()
32    }
33
34    #[cfg(feature = "blocking")]
35    fn conform(&mut self) -> Result<(), super::super::UrlError> {
36        use super::super::errors::*;
37
38        let tokio = runtime()?;
39        // TODO: can we get the MIME type here for format?
40        let response = tokio.block_on(self.context.http_client.head(self.url.clone()).send())?;
41        if response.status().is_success() { Ok(()) } else { Err(UrlError::new_io_not_found(self)) }
42    }
43
44    #[cfg(feature = "async")]
45    fn conform_async(&self) -> Result<ConformFuture, super::super::UrlError> {
46        use super::super::errors::*;
47
48        async fn conform_async(url: HttpUrl) -> Result<UrlRef, UrlError> {
49            let response = url.context.http_client.head(url.url.clone()).send().await?;
50            if response.status().is_success() {
51                Ok(url.into())
52            } else {
53                Err(UrlError::new_io_not_found(url.url.as_str()))
54            }
55        }
56
57        Ok(Box::pin(conform_async(self.clone())))
58    }
59
60    #[cfg(feature = "blocking")]
61    fn open(&self) -> Result<ReadRef, super::super::UrlError> {
62        use kutil::io::stream::{bytes::*, *};
63
64        let runtime = runtime()?;
65        let response = runtime.block_on(self.context.http_client.get(self.url.clone()).send())?;
66        let stream = response.bytes_stream();
67        let reader = BlockingBytesStreamReader::new(BlockingStream::new(stream, runtime));
68        Ok(Box::new(reader))
69    }
70
71    #[cfg(feature = "async")]
72    fn open_async(&self) -> Result<OpenFuture, super::super::UrlError> {
73        use {super::super::errors::*, kutil::io::stream::bytes::*};
74
75        async fn open_async(url: HttpUrl) -> Result<AsyncReadRef, UrlError> {
76            let response = url.context.http_client.get(url.url.clone()).send().await?;
77            let stream = response.bytes_stream();
78            let reader = AsyncBytesStreamReader::new(stream);
79            Ok(Box::pin(reader))
80        }
81
82        Ok(Box::pin(open_async(self.clone())))
83    }
84}
85
86#[cfg(feature = "blocking")]
87fn runtime() -> Result<tokio::runtime::Runtime, super::super::UrlError> {
88    Ok(tokio::runtime::Builder::new_current_thread().enable_all().build()?)
89}