Create easy common interface for off-thread network listeners, and remove the CORS-specific reimplementation of async networking.

This commit is contained in:
Josh Matthews 2015-03-05 10:34:30 -05:00
parent f7ac1f1876
commit 1ca9ff56c8
4 changed files with 110 additions and 78 deletions

View file

@ -9,8 +9,14 @@
//! This library will eventually become the core of the Fetch crate
//! with CORSRequest being expanded into FetchRequest (etc)
use network_listener::{NetworkListener, PreInvoke};
use script_task::ScriptChan;
use net_traits::{AsyncResponseTarget, AsyncResponseListener, ResponseAction, Metadata};
use std::ascii::AsciiExt;
use std::borrow::ToOwned;
use std::cell::RefCell;
use std::sync::{Arc, Mutex};
use time;
use time::{now, Timespec};
@ -27,14 +33,12 @@ use hyper::status::StatusClass::Success;
use url::{SchemeData, Url};
use util::task::spawn_named;
/// Interface for network listeners concerned with CORS checks. Proper network requests
/// should be initiated from this method, based on the response provided.
pub trait AsyncCORSResponseListener {
fn response_available(&self, response: CORSResponse);
}
pub trait AsyncCORSResponseTarget {
fn invoke_with_listener(&self, response: CORSResponse);
}
#[derive(Clone)]
pub struct CORSRequest {
pub origin: Url,
@ -98,13 +102,48 @@ impl CORSRequest {
}
}
pub fn http_fetch_async(&self, listener: Box<AsyncCORSResponseTarget + Send>) {
pub fn http_fetch_async(&self,
listener: Box<AsyncCORSResponseListener+Send>,
script_chan: Box<ScriptChan+Send>) {
struct CORSContext {
listener: Box<AsyncCORSResponseListener+Send>,
response: RefCell<Option<CORSResponse>>,
}
// This is shoe-horning the CORSReponse stuff into the rest of the async network
// framework right now. It would be worth redesigning http_fetch to do this properly.
impl AsyncResponseListener for CORSContext {
fn headers_available(&self, _metadata: Metadata) {
}
fn data_available(&self, _payload: Vec<u8>) {
}
fn response_complete(&self, _status: Result<(), String>) {
let response = self.response.borrow_mut().take().unwrap();
self.listener.response_available(response);
}
}
impl PreInvoke for CORSContext {}
let context = CORSContext {
listener: listener,
response: RefCell::new(None),
};
let listener = NetworkListener {
context: Arc::new(Mutex::new(context)),
script_chan: script_chan,
};
// TODO: this exists only to make preflight check non-blocking
// perhaps should be handled by the resource task?
let req = self.clone();
spawn_named("cors".to_owned(), move || {
let response = req.http_fetch();
listener.invoke_with_listener(response);
let mut context = listener.context.lock();
let context = context.as_mut().unwrap();
*context.response.borrow_mut() = Some(response);
listener.invoke_with_listener(ResponseAction::ResponseComplete(Ok(())));
});
}