diff --git a/components/net/fetch/methods.rs b/components/net/fetch/methods.rs index 868d284707f..1b4c43195ea 100644 --- a/components/net/fetch/methods.rs +++ b/components/net/fetch/methods.rs @@ -14,6 +14,7 @@ use hyper::header::{IfNoneMatch, Pragma, Location, QualityItem, Referer as Refer use hyper::method::Method; use hyper::mime::{Mime, SubLevel, TopLevel}; use hyper::status::StatusCode; +use mime_guess::guess_mime_type; use net_traits::AsyncFetchListener; use net_traits::request::{CacheMode, CredentialsMode, Type, Origin, Window}; use net_traits::request::{RedirectMode, Referer, Request, RequestMode, ResponseTainting}; @@ -21,6 +22,7 @@ use net_traits::response::{HttpsState, TerminationReason}; use net_traits::response::{Response, ResponseBody, ResponseType}; use resource_thread::CancellationListener; use std::collections::HashSet; +use std::fs::File; use std::io::Read; use std::iter::FromIterator; use std::rc::Rc; @@ -157,6 +159,7 @@ fn main_fetch(request: Rc, cache: &mut CORSCache, cors_flag: bool, recu if (same_origin && !cors_flag ) || (current_url.scheme() == "data" && request.same_origin_data.get()) || + (current_url.scheme() == "file" && request.same_origin_data.get()) || current_url.scheme() == "about" || request.mode == RequestMode::Navigate { @@ -317,7 +320,29 @@ fn basic_fetch(request: Rc, cache: &mut CORSCache) -> Response { } }, - "blob" | "file" | "ftp" => { + "file" => { + if *request.method.borrow() == Method::Get { + match url.to_file_path() { + Ok(file_path) => { + File::open(file_path.clone()).ok().map_or(Response::network_error(), |mut file| { + let mut bytes = vec![]; + let _ = file.read_to_end(&mut bytes); + let mime = guess_mime_type(file_path); + + let mut response = Response::new(); + *response.body.lock().unwrap() = ResponseBody::Done(bytes); + response.headers.set(ContentType(mime)); + response + }) + }, + _ => Response::network_error() + } + } else { + Response::network_error() + } + }, + + "blob" | "ftp" => { // XXXManishearth handle these panic!("Unimplemented scheme for Fetch") }, diff --git a/tests/unit/net/fetch.rs b/tests/unit/net/fetch.rs index 98b15fd8b8c..d880e3937c0 100644 --- a/tests/unit/net/fetch.rs +++ b/tests/unit/net/fetch.rs @@ -18,6 +18,8 @@ use net::fetch::methods::{fetch, fetch_async, fetch_with_cors_cache}; use net_traits::AsyncFetchListener; use net_traits::request::{Origin, RedirectMode, Referer, Request, RequestMode}; use net_traits::response::{CacheState, Response, ResponseBody, ResponseType}; +use std::fs::File; +use std::io::Read; use std::rc::Rc; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::mpsc::{Sender, channel}; @@ -25,6 +27,7 @@ use std::sync::{Arc, Mutex}; use time::{self, Duration}; use unicase::UniCase; use url::{Origin as UrlOrigin, Url}; +use util::resource_files::resources_dir_path; // TODO write a struct that impls Handler for storing test values @@ -140,6 +143,36 @@ fn test_fetch_data() { } } +#[test] +fn test_fetch_file() { + + let mut path = resources_dir_path(); + path.push("servo.css"); + + let url = Url::from_file_path(path.clone()).unwrap(); + let origin = Origin::Origin(url.origin()); + let request = Request::new(url, Some(origin), false); + request.same_origin_data.set(true); + + let fetch_response = fetch(Rc::new(request)); + assert!(!fetch_response.is_network_error()); + assert_eq!(fetch_response.headers.len(), 1); + let content_type: &ContentType = fetch_response.headers.get().unwrap(); + assert!(**content_type == Mime(TopLevel::Text, SubLevel::Css, vec![])); + + let resp_body = fetch_response.body.lock().unwrap(); + let mut file = File::open(path).unwrap(); + let mut bytes = vec![]; + let _ = file.read_to_end(&mut bytes); + + match *resp_body { + ResponseBody::Done(ref val) => { + assert_eq!(val, &bytes); + }, + _ => panic!() + } +} + #[test] fn test_cors_preflight_fetch() { static ACK: &'static [u8] = b"ACK";