1use std::future::Future;
6use std::pin::Pin;
7
8use data_url::DataUrl;
9use http::HeaderValue;
10use net_traits::http_status::HttpStatus;
11use net_traits::request::Request;
12use net_traits::response::{Response, ResponseBody};
13use net_traits::{NetworkError, ResourceFetchTiming};
14
15use crate::fetch::methods::{DoneChannel, FetchContext};
16use crate::protocols::ProtocolHandler;
17
18#[derive(Default)]
19pub struct DataProtocolHander {}
20
21impl ProtocolHandler for DataProtocolHander {
22 fn load(
23 &self,
24 request: &mut Request,
25 _done_chan: &mut DoneChannel,
26 _context: &FetchContext,
27 ) -> Pin<Box<dyn Future<Output = Response> + Send>> {
28 let url = request.current_url();
29
30 assert_eq!(url.scheme(), "data");
31
32 let response = match DataUrl::process(url.clone().as_str()) {
33 Ok(data_url) => match data_url.decode_to_vec() {
34 Ok((bytes, _fragment_id)) => {
35 let mut response =
36 Response::new(url, ResourceFetchTiming::new(request.timing_type()));
37 *response.body.lock() = ResponseBody::Done(bytes);
38
39 if let Ok(content_type_header_value) =
40 HeaderValue::from_str(&data_url.mime_type().to_string())
41 {
42 response
43 .headers
44 .insert(http::header::CONTENT_TYPE, content_type_header_value);
45 }
46
47 response.status = HttpStatus::default();
48 Some(response)
49 },
50 Err(_) => None,
51 },
52 Err(_) => None,
53 }
54 .unwrap_or_else(|| {
55 Response::network_error(NetworkError::ResourceLoadError(
56 "Decoding data URL failed".into(),
57 ))
58 });
59
60 Box::pin(std::future::ready(response))
61 }
62
63 fn is_fetchable(&self) -> bool {
64 true
65 }
66}