aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/net/fetch
diff options
context:
space:
mode:
authorJack Moffitt <jack@metajack.im>2014-08-28 09:34:23 -0600
committerJack Moffitt <jack@metajack.im>2014-09-08 20:21:42 -0600
commitc6ab60dbfc6da7b4f800c9e40893c8b58413960c (patch)
treed1d74076cf7fa20e4f77ec7cb82cae98b67362cb /src/components/net/fetch
parentdb2f642c32fc5bed445bb6f2e45b0f6f0b4342cf (diff)
downloadservo-c6ab60dbfc6da7b4f800c9e40893c8b58413960c.tar.gz
servo-c6ab60dbfc6da7b4f800c9e40893c8b58413960c.zip
Cargoify servo
Diffstat (limited to 'src/components/net/fetch')
-rw-r--r--src/components/net/fetch/cors_cache.rs316
-rw-r--r--src/components/net/fetch/request.rs149
-rw-r--r--src/components/net/fetch/response.rs144
3 files changed, 0 insertions, 609 deletions
diff --git a/src/components/net/fetch/cors_cache.rs b/src/components/net/fetch/cors_cache.rs
deleted file mode 100644
index fb6676e8064..00000000000
--- a/src/components/net/fetch/cors_cache.rs
+++ /dev/null
@@ -1,316 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-//! An implementation of the [CORS preflight cache](http://fetch.spec.whatwg.org/#cors-preflight-cache)
-//! For now this library is XHR-specific.
-//! For stuff involving `<img>`, `<iframe>`, `<form>`, etc please check what
-//! the request mode should be and compare with the fetch spec
-//! This library will eventually become the core of the Fetch crate
-//! with CORSRequest being expanded into FetchRequest (etc)
-
-use http::method::Method;
-use std::ascii::StrAsciiExt;
-use std::comm::{Sender, Receiver, channel};
-use time;
-use time::{now, Timespec};
-use url::Url;
-
-/// Union type for CORS cache entries
-///
-/// Each entry might pertain to a header or method
-#[deriving(Clone)]
-pub enum HeaderOrMethod {
- HeaderData(String),
- MethodData(Method)
-}
-
-impl HeaderOrMethod {
- fn match_header(&self, header_name: &str) -> bool {
- match *self {
- HeaderData(ref s) => s.as_slice().eq_ignore_ascii_case(header_name),
- _ => false
- }
- }
-
- fn match_method(&self, method: &Method) -> bool {
- match *self {
- MethodData(ref m) => m == method,
- _ => false
- }
- }
-}
-
-/// An entry in the CORS cache
-#[deriving(Clone)]
-pub struct CORSCacheEntry {
- pub origin: Url,
- pub url: Url,
- pub max_age: uint,
- pub credentials: bool,
- pub header_or_method: HeaderOrMethod,
- created: Timespec
-}
-
-impl CORSCacheEntry {
- fn new (origin:Url, url: Url, max_age: uint, credentials: bool, header_or_method: HeaderOrMethod) -> CORSCacheEntry {
- CORSCacheEntry {
- origin: origin,
- url: url,
- max_age: max_age,
- credentials: credentials,
- header_or_method: header_or_method,
- created: time::now().to_timespec()
- }
- }
-}
-
-/// Properties of Request required to cache match.
-pub struct CacheRequestDetails {
- pub origin: Url,
- pub destination: Url,
- pub credentials: bool
-}
-
-/// Trait for a generic CORS Cache
-pub trait CORSCache {
- /// [Clear the cache](http://fetch.spec.whatwg.org/#concept-cache-clear)
- fn clear (&mut self, request: CacheRequestDetails);
-
- /// Remove old entries
- fn cleanup(&mut self);
-
- /// Returns true if an entry with a [matching header](http://fetch.spec.whatwg.org/#concept-cache-match-header) is found
- fn match_header(&mut self, request: CacheRequestDetails, header_name: &str) -> bool;
-
- /// Updates max age if an entry for a [matching header](http://fetch.spec.whatwg.org/#concept-cache-match-header) is found.
- ///
- /// If not, it will insert an equivalent entry
- fn match_header_and_update(&mut self, request: CacheRequestDetails, header_name: &str, new_max_age: uint) -> bool;
-
- /// Returns true if an entry with a [matching method](http://fetch.spec.whatwg.org/#concept-cache-match-method) is found
- fn match_method(&mut self, request: CacheRequestDetails, method: Method) -> bool;
-
- /// Updates max age if an entry for [a matching method](http://fetch.spec.whatwg.org/#concept-cache-match-method) is found.
- ///
- /// If not, it will insert an equivalent entry
- fn match_method_and_update(&mut self, request: CacheRequestDetails, method: Method, new_max_age: uint) -> bool;
- /// Insert an entry
- fn insert(&mut self, entry: CORSCacheEntry);
-}
-
-/// A simple, vector-based CORS Cache
-#[deriving(Clone)]
-#[unstable = "This might later be replaced with a HashMap-like entity, though that requires a separate Origin struct"]
-pub struct BasicCORSCache(Vec<CORSCacheEntry>);
-
-impl BasicCORSCache {
- fn find_entry_by_header<'a>(&'a mut self, request: &CacheRequestDetails, header_name: &str) -> Option<&'a mut CORSCacheEntry> {
- self.cleanup();
- let BasicCORSCache(ref mut buf) = *self;
- let entry = buf.mut_iter().find(|e| e.origin.scheme == request.origin.scheme &&
- e.origin.host() == request.origin.host() &&
- e.origin.port() == request.origin.port() &&
- e.url == request.destination &&
- e.credentials == request.credentials &&
- e.header_or_method.match_header(header_name));
- entry
- }
-
- fn find_entry_by_method<'a>(&'a mut self, request: &CacheRequestDetails, method: Method) -> Option<&'a mut CORSCacheEntry> {
- // we can take the method from CORSRequest itself
- self.cleanup();
- let BasicCORSCache(ref mut buf) = *self;
- let entry = buf.mut_iter().find(|e| e.origin.scheme == request.origin.scheme &&
- e.origin.host() == request.origin.host() &&
- e.origin.port() == request.origin.port() &&
- e.url == request.destination &&
- e.credentials == request.credentials &&
- e.header_or_method.match_method(&method));
- entry
- }
-}
-
-impl CORSCache for BasicCORSCache {
- /// http://fetch.spec.whatwg.org/#concept-cache-clear
- #[allow(dead_code)]
- fn clear (&mut self, request: CacheRequestDetails) {
- let BasicCORSCache(buf) = self.clone();
- let new_buf: Vec<CORSCacheEntry> = buf.move_iter().filter(|e| e.origin == request.origin && request.destination == e.url).collect();
- *self = BasicCORSCache(new_buf);
- }
-
- // Remove old entries
- fn cleanup(&mut self) {
- let BasicCORSCache(buf) = self.clone();
- let now = time::now().to_timespec();
- let new_buf: Vec<CORSCacheEntry> = buf.move_iter().filter(|e| now.sec > e.created.sec + e.max_age as i64).collect();
- *self = BasicCORSCache(new_buf);
- }
-
- fn match_header(&mut self, request: CacheRequestDetails, header_name: &str) -> bool {
- self.find_entry_by_header(&request, header_name).is_some()
- }
-
- fn match_header_and_update(&mut self, request: CacheRequestDetails, header_name: &str, new_max_age: uint) -> bool {
- match self.find_entry_by_header(&request, header_name).map(|e| e.max_age = new_max_age) {
- Some(_) => true,
- None => {
- self.insert(CORSCacheEntry::new(request.origin, request.destination, new_max_age,
- request.credentials, HeaderData(header_name.to_string())));
- false
- }
- }
- }
-
- fn match_method(&mut self, request: CacheRequestDetails, method: Method) -> bool {
- self.find_entry_by_method(&request, method).is_some()
- }
-
- fn match_method_and_update(&mut self, request: CacheRequestDetails, method: Method, new_max_age: uint) -> bool {
- match self.find_entry_by_method(&request, method.clone()).map(|e| e.max_age = new_max_age) {
- Some(_) => true,
- None => {
- self.insert(CORSCacheEntry::new(request.origin, request.destination, new_max_age,
- request.credentials, MethodData(method)));
- false
- }
- }
- }
-
- fn insert(&mut self, entry: CORSCacheEntry) {
- self.cleanup();
- let BasicCORSCache(ref mut buf) = *self;
- buf.push(entry);
- }
-}
-
-/// Various messages that can be sent to a CORSCacheTask
-pub enum CORSCacheTaskMsg {
- Clear(CacheRequestDetails, Sender<()>),
- Cleanup(Sender<()>),
- MatchHeader(CacheRequestDetails, String, Sender<bool>),
- MatchHeaderUpdate(CacheRequestDetails, String, uint, Sender<bool>),
- MatchMethod(CacheRequestDetails, Method, Sender<bool>),
- MatchMethodUpdate(CacheRequestDetails, Method, uint, Sender<bool>),
- Insert(CORSCacheEntry, Sender<()>),
- ExitMsg
-}
-
-/// A Sender to a CORSCacheTask
-///
-/// This can be used as a CORS Cache.
-/// The methods on this type block until they can run, and it behaves similar to a mutex
-pub type CORSCacheSender = Sender<CORSCacheTaskMsg>;
-
-impl CORSCache for CORSCacheSender {
- fn clear (&mut self, request: CacheRequestDetails) {
- let (tx, rx) = channel();
- self.send(Clear(request, tx));
- let _ = rx.recv_opt();
- }
-
- fn cleanup(&mut self) {
- let (tx, rx) = channel();
- self.send(Cleanup(tx));
- let _ = rx.recv_opt();
- }
-
- fn match_header(&mut self, request: CacheRequestDetails, header_name: &str) -> bool {
- let (tx, rx) = channel();
- self.send(MatchHeader(request, header_name.to_string(), tx));
- rx.recv_opt().unwrap_or(false)
- }
-
- fn match_header_and_update(&mut self, request: CacheRequestDetails, header_name: &str, new_max_age: uint) -> bool {
- let (tx, rx) = channel();
- self.send(MatchHeaderUpdate(request, header_name.to_string(), new_max_age, tx));
- rx.recv_opt().unwrap_or(false)
- }
-
- fn match_method(&mut self, request: CacheRequestDetails, method: Method) -> bool {
- let (tx, rx) = channel();
- self.send(MatchMethod(request, method, tx));
- rx.recv_opt().unwrap_or(false)
- }
-
- fn match_method_and_update(&mut self, request: CacheRequestDetails, method: Method, new_max_age: uint) -> bool {
- let (tx, rx) = channel();
- self.send(MatchMethodUpdate(request, method, new_max_age, tx));
- rx.recv_opt().unwrap_or(false)
- }
-
- fn insert(&mut self, entry: CORSCacheEntry) {
- let (tx, rx) = channel();
- self.send(Insert(entry, tx));
- let _ = rx.recv_opt();
- }
-}
-
-/// A simple task-based CORS Cache that can be sent messages
-///
-/// #Example
-/// ```
-/// let task = CORSCacheTask::new();
-/// let builder = TaskBuilder::new().named("XHRTask");
-/// let mut sender = task.get_sender();
-/// builder.spawn(proc() { task.run() });
-/// sender.insert(CORSCacheEntry::new(/* parameters here */));
-/// ```
-pub struct CORSCacheTask {
- receiver: Receiver<CORSCacheTaskMsg>,
- cache: BasicCORSCache,
- sender: CORSCacheSender
-}
-
-impl CORSCacheTask {
- pub fn new() -> CORSCacheTask {
- let (tx, rx) = channel();
- CORSCacheTask {
- receiver: rx,
- cache: BasicCORSCache(vec![]),
- sender: tx
- }
- }
-
- /// Provides a sender to the cache task
- pub fn get_sender(&self) -> CORSCacheSender {
- self.sender.clone()
- }
-
- /// Runs the cache task
- /// This blocks the current task, so it is advised
- /// to spawn a new task for this
- /// Send ExitMsg to the associated Sender to exit
- pub fn run(&mut self) {
- loop {
- match self.receiver.recv() {
- Clear(request, tx) => {
- self.cache.clear(request);
- tx.send(());
- },
- Cleanup(tx) => {
- self.cache.cleanup();
- tx.send(());
- },
- MatchHeader(request, header, tx) => {
- tx.send(self.cache.match_header(request, header.as_slice()));
- },
- MatchHeaderUpdate(request, header, new_max_age, tx) => {
- tx.send(self.cache.match_header_and_update(request, header.as_slice(), new_max_age));
- },
- MatchMethod(request, method, tx) => {
- tx.send(self.cache.match_method(request, method));
- },
- MatchMethodUpdate(request, method, new_max_age, tx) => {
- tx.send(self.cache.match_method_and_update(request, method, new_max_age));
- },
- Insert(entry, tx) => {
- self.cache.insert(entry);
- tx.send(());
- },
- ExitMsg => break
- }
- }
- }
-}
diff --git a/src/components/net/fetch/request.rs b/src/components/net/fetch/request.rs
deleted file mode 100644
index c14efe9c59e..00000000000
--- a/src/components/net/fetch/request.rs
+++ /dev/null
@@ -1,149 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-use url::Url;
-use http::method::{Get, Method};
-use http::headers::request::HeaderCollection;
-use fetch::cors_cache::CORSCache;
-use fetch::response::Response;
-
-/// A [request context](http://fetch.spec.whatwg.org/#concept-request-context)
-pub enum Context {
- Audio, Beacon, CSPreport, Download, Embed, Eventsource,
- Favicon, Fetch, Font, Form, Frame, Hyperlink, IFrame, Image,
- ImageSet, Import, Internal, Location, Manifest, Object, Ping,
- Plugin, Prefetch, Script, ServiceWorker, SharedWorker, Subresource,
- Style, Track, Video, Worker, XMLHttpRequest, XSLT
-}
-
-/// A [request context frame type](http://fetch.spec.whatwg.org/#concept-request-context-frame-type)
-pub enum ContextFrameType {
- Auxiliary,
- TopLevel,
- Nested,
- ContextNone
-}
-
-/// A [referer](http://fetch.spec.whatwg.org/#concept-request-referrer)
-pub enum Referer {
- RefererNone,
- Client,
- RefererUrl(Url)
-}
-
-/// A [request mode](http://fetch.spec.whatwg.org/#concept-request-mode)
-pub enum RequestMode {
- SameOrigin,
- NoCORS,
- CORSMode,
- ForcedPreflightMode
-}
-
-/// Request [credentials mode](http://fetch.spec.whatwg.org/#concept-request-credentials-mode)
-pub enum CredentialsMode {
- Omit,
- CredentialsSameOrigin,
- Include
-}
-
-/// [Response tainting](http://fetch.spec.whatwg.org/#concept-request-response-tainting)
-pub enum ResponseTainting {
- Basic,
- CORSTainting,
- Opaque
-}
-
-/// A [Request](http://fetch.spec.whatwg.org/#requests) as defined by the Fetch spec
-pub struct Request {
- pub method: Method,
- pub url: Url,
- pub headers: HeaderCollection,
- pub unsafe_request: bool,
- pub body: Option<Vec<u8>>,
- pub preserve_content_codings: bool,
- // pub client: GlobalRef, // XXXManishearth copy over only the relevant fields of the global scope,
- // not the entire scope to avoid the libscript dependency
- pub skip_service_worker: bool,
- pub context: Context,
- pub context_frame_type: ContextFrameType,
- pub origin: Option<Url>,
- pub force_origin_header: bool,
- pub same_origin_data: bool,
- pub referer: Referer,
- pub authentication: bool,
- pub sync: bool,
- pub mode: RequestMode,
- pub credentials_mode: CredentialsMode,
- pub use_url_credentials: bool,
- pub manual_redirect: bool,
- pub redirect_count: uint,
- pub response_tainting: ResponseTainting,
- pub cache: Option<Box<CORSCache>>
-}
-
-impl Request {
- pub fn new(url: Url, context: Context) -> Request {
- Request {
- method: Get,
- url: url,
- headers: HeaderCollection::new(),
- unsafe_request: false,
- body: None,
- preserve_content_codings: false,
- skip_service_worker: false,
- context: context,
- context_frame_type: ContextNone,
- origin: None,
- force_origin_header: false,
- same_origin_data: false,
- referer: Client,
- authentication: false,
- sync: false,
- mode: NoCORS,
- credentials_mode: Omit,
- use_url_credentials: false,
- manual_redirect: false,
- redirect_count: 0,
- response_tainting: Basic,
- cache: None
- }
- }
-
- /// [Basic fetch](http://fetch.spec.whatwg.org#basic-fetch)
- pub fn basic_fetch(&mut self) -> Response {
- match self.url.scheme.as_slice() {
- "about" => match self.url.non_relative_scheme_data() {
- Some(s) if s.as_slice() == "blank" => {
- let mut response = Response::new();
- let _ = response.headers.insert_raw("Content-Type".to_string(), b"text/html;charset=utf-8");
- response
- },
- _ => Response::network_error()
- },
- "http" | "https" => {
- self.http_fetch(false, false, false)
- },
- "blob" | "data" | "file" | "ftp" => {
- // XXXManishearth handle these
- fail!("Unimplemented scheme for Fetch")
- },
-
- _ => Response::network_error()
- }
- }
-
- // [HTTP fetch](http://fetch.spec.whatwg.org#http-fetch)
- pub fn http_fetch(&mut self, _cors_flag: bool, cors_preflight_flag: bool, _authentication_fetch_flag: bool) -> Response {
- let response = Response::new();
- // TODO: Service worker fetch
- // Step 3
- // Substep 1
- self.skip_service_worker = true;
- // Substep 2
- if cors_preflight_flag {
- // XXXManishearth stuff goes here
- }
- response
- }
-}
diff --git a/src/components/net/fetch/response.rs b/src/components/net/fetch/response.rs
deleted file mode 100644
index 359ec6aa394..00000000000
--- a/src/components/net/fetch/response.rs
+++ /dev/null
@@ -1,144 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-use url::Url;
-use http::status::{Status, UnregisteredStatus};
-use StatusOk = http::status::Ok;
-use http::headers::HeaderEnum;
-use http::headers::response::HeaderCollection;
-use std::ascii::OwnedStrAsciiExt;
-use std::comm::Receiver;
-
-/// [Response type](http://fetch.spec.whatwg.org/#concept-response-type)
-#[deriving(Clone, PartialEq)]
-pub enum ResponseType {
- Basic,
- CORS,
- Default,
- Error,
- Opaque
-}
-
-/// [Response termination reason](http://fetch.spec.whatwg.org/#concept-response-termination-reason)
-#[deriving(Clone)]
-pub enum TerminationReason {
- EndUserAbort,
- Fatal,
- Timeout
-}
-
-/// The response body can still be pushed to after fetch
-/// This provides a way to store unfinished response bodies
-#[unstable = "I haven't yet decided exactly how the interface for this will be"]
-#[deriving(Clone)]
-pub enum ResponseBody {
- Empty, // XXXManishearth is this necessary, or is Done(vec![]) enough?
- Receiving(Vec<u8>),
- Done(Vec<u8>),
-}
-
-#[unstable = "I haven't yet decided exactly how the interface for this will be"]
-pub enum ResponseMsg {
- Chunk(Vec<u8>),
- Finished,
- Errored
-}
-
-#[unstable = "I haven't yet decided exactly how the interface for this will be"]
-pub struct ResponseLoader {
- response: Response,
- chan: Receiver<ResponseMsg>
-}
-
-/// A [Response](http://fetch.spec.whatwg.org/#concept-response) as defined by the Fetch spec
-#[deriving(Clone)]
-pub struct Response {
- pub response_type: ResponseType,
- pub termination_reason: Option<TerminationReason>,
- pub url: Option<Url>,
- pub status: Status,
- pub headers: HeaderCollection,
- pub body: ResponseBody,
- /// [Internal response](http://fetch.spec.whatwg.org/#concept-internal-response), only used if the Response is a filtered response
- pub internal_response: Option<Box<Response>>,
-}
-
-impl Response {
- pub fn new() -> Response {
- Response {
- response_type: Default,
- termination_reason: None,
- url: None,
- status: StatusOk,
- headers: HeaderCollection::new(),
- body: Empty,
- internal_response: None
- }
- }
-
- pub fn network_error() -> Response {
- Response {
- response_type: Error,
- termination_reason: None,
- url: None,
- status: UnregisteredStatus(0, "".to_string()),
- headers: HeaderCollection::new(),
- body: Empty,
- internal_response: None
- }
- }
-
- pub fn is_network_error(&self) -> bool {
- match self.response_type {
- Error => true,
- _ => false
- }
- }
-
- /// Convert to a filtered response, of type `filter_type`.
- /// Do not use with type Error or Default
- pub fn to_filtered(self, filter_type: ResponseType) -> Response {
- assert!(filter_type != Error);
- assert!(filter_type != Default);
- if self.is_network_error() {
- return self;
- }
- let old_headers = self.headers.clone();
- let mut response = self.clone();
- response.internal_response = Some(box self);
- match filter_type {
- Default | Error => unreachable!(),
- Basic => {
- let mut headers = HeaderCollection::new();
- for h in old_headers.iter() {
- match h.header_name().into_ascii_lower().as_slice() {
- "set-cookie" | "set-cookie2" => {},
- _ => headers.insert(h)
- }
- }
- response.headers = headers;
- response.response_type = filter_type;
- },
- CORS => {
- let mut headers = HeaderCollection::new();
- for h in old_headers.iter() {
- match h.header_name().into_ascii_lower().as_slice() {
- "cache-control" | "content-language" |
- "content-type" | "expires" | "last-modified" | "Pragma" => {},
- // XXXManishearth handle Access-Control-Expose-Headers
- _ => headers.insert(h)
- }
- }
- response.headers = headers;
- response.response_type = filter_type;
- },
- Opaque => {
- response.headers = HeaderCollection::new();
- response.status = UnregisteredStatus(0, "".to_string());
- response.body = Empty;
- }
- }
- response
- }
-}