use std::future::Future;
use std::pin::Pin;
use data_url::DataUrl;
use headers::HeaderValue;
use net_traits::http_status::HttpStatus;
use net_traits::request::Request;
use net_traits::response::{Response, ResponseBody};
use net_traits::{NetworkError, ResourceFetchTiming};
use crate::fetch::methods::{DoneChannel, FetchContext};
use crate::protocols::ProtocolHandler;
#[derive(Default)]
pub struct DataProtocolHander {}
impl ProtocolHandler for DataProtocolHander {
fn load(
&self,
request: &mut Request,
_done_chan: &mut DoneChannel,
_context: &FetchContext,
) -> Pin<Box<dyn Future<Output = Response> + Send>> {
let url = request.current_url();
assert_eq!(url.scheme(), "data");
let response = match DataUrl::process(url.clone().as_str()) {
Ok(data_url) => match data_url.decode_to_vec() {
Ok((bytes, _fragment_id)) => {
let mut response =
Response::new(url, ResourceFetchTiming::new(request.timing_type()));
*response.body.lock().unwrap() = ResponseBody::Done(bytes);
let mime = data_url.mime_type();
response.headers.insert(
http::header::CONTENT_TYPE,
HeaderValue::from_str(&mime.to_string()).unwrap(),
);
response.status = HttpStatus::default();
Some(response)
},
Err(_) => None,
},
Err(_) => None,
}
.unwrap_or_else(|| {
Response::network_error(NetworkError::Internal("Decoding data URL failed".into()))
});
Box::pin(std::future::ready(response))
}
fn is_fetchable(&self) -> bool {
true
}
}