core: Introduce `Request`

Which holds both a URL and what was `RequestOptions` formerly.
This commit is contained in:
relrelb 2022-06-11 11:55:17 +03:00 committed by relrelb
parent 115f15806e
commit f643048c1c
13 changed files with 133 additions and 144 deletions

View File

@ -7,7 +7,7 @@ use crate::avm1::scope::Scope;
use crate::avm1::{
fscommand, globals, scope, skip_actions, start_drag, ArrayObject, ScriptObject, Value,
};
use crate::backend::navigator::{NavigationMethod, RequestOptions};
use crate::backend::navigator::{NavigationMethod, Request};
use crate::context::UpdateContext;
use crate::display_object::{DisplayObject, MovieClip, TDisplayObject, TDisplayObjectContainer};
use crate::ecma_conversions::f64_to_wrapping_u32;
@ -1154,8 +1154,7 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
let future = self.context.load_manager.load_movie_into_clip(
self.context.player.clone(),
level,
&url,
RequestOptions::get(),
Request::get(url),
None,
None,
);
@ -1246,15 +1245,14 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
.unwrap()
.object()
.coerce_to_object(self);
let (url, opts) = self.locals_into_request_options(
&url,
let request = self.locals_into_request(
url,
NavigationMethod::from_send_vars_method(action.send_vars_method()),
);
let future = self.context.load_manager.load_form_into_object(
self.context.player.clone(),
target_obj,
&url,
opts,
request,
);
self.context.navigator.spawn_future(future);
}
@ -1263,22 +1261,20 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
} else if action.is_target_sprite() {
// `loadMovie`, `unloadMovie` or `unloadMovieNum` call.
if let Some(clip_target) = clip_target {
let (url, opts) = self.locals_into_request_options(
&url,
NavigationMethod::from_send_vars_method(action.send_vars_method()),
);
if url.is_empty() {
// Blank URL on movie loads = unload!
if let Some(mut mc) = clip_target.as_movie_clip() {
mc.replace_with_movie(self.context.gc_context, None)
}
} else {
let request = self.locals_into_request(
url,
NavigationMethod::from_send_vars_method(action.send_vars_method()),
);
let future = self.context.load_manager.load_movie_into_clip(
self.context.player.clone(),
clip_target,
&url,
opts,
request,
None,
None,
);
@ -1292,8 +1288,7 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
let future = self.context.load_manager.load_movie_into_clip(
self.context.player.clone(),
clip_target,
&url.to_utf8_lossy(),
RequestOptions::get(),
Request::get(url.to_utf8_lossy().into_owned()),
None,
None,
);
@ -2295,14 +2290,14 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
form_values
}
/// Construct request options for a fetch operation that may sends object properties as
/// form data in the request body or URL.
pub fn object_into_request_options<'c>(
/// Construct a request for a fetch operation that may send object properties as form data in
/// the request body or URL.
pub fn object_into_request(
&mut self,
object: Object<'gc>,
url: &'c WStr,
url: AvmString<'gc>,
method: Option<NavigationMethod>,
) -> (Cow<'c, str>, RequestOptions) {
) -> Request {
match method {
Some(method) => {
let vars = self.object_into_form_values(object);
@ -2311,24 +2306,20 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
.finish();
match method {
NavigationMethod::Get if url.find(b'?').is_none() => (
Cow::Owned(format!("{}?{}", url, qstring)),
RequestOptions::get(),
),
NavigationMethod::Get => (
Cow::Owned(format!("{}&{}", url, qstring)),
RequestOptions::get(),
),
NavigationMethod::Post => (
url.to_utf8_lossy(),
RequestOptions::post(Some((
NavigationMethod::Get if !url.contains(b'?') => {
Request::get(format!("{}?{}", url, qstring))
}
NavigationMethod::Get => Request::get(format!("{}&{}", url, qstring)),
NavigationMethod::Post => Request::post(
url.to_utf8_lossy().into_owned(),
Some((
qstring.as_bytes().to_owned(),
"application/x-www-form-urlencoded".to_string(),
))),
)),
),
}
}
None => (url.to_utf8_lossy(), RequestOptions::get()),
None => Request::get(url.to_utf8_lossy().into_owned()),
}
}
@ -2344,16 +2335,16 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
self.object_into_form_values(locals)
}
/// Construct request options for a fetch operation that may send locals as
/// form data in the request body or URL.
pub fn locals_into_request_options<'c>(
/// Construct a request for a fetch operation that may send locals as form data in the request
/// body or URL.
pub fn locals_into_request(
&mut self,
url: &'c WStr,
url: AvmString<'gc>,
method: Option<NavigationMethod>,
) -> (Cow<'c, str>, RequestOptions) {
) -> Request {
let scope = self.scope_cell();
let locals = scope.read().locals_cell();
self.object_into_request_options(locals, url, method)
self.object_into_request(locals, url, method)
}
/// Resolves a target value to a display object, relative to a starting display object.

View File

@ -8,7 +8,7 @@ use crate::avm1::property::Attribute;
use crate::avm1::property_decl::{define_properties_on, Declaration};
use crate::avm1::{Object, ScriptObject, TObject, Value};
use crate::avm_warn;
use crate::backend::navigator::{NavigationMethod, RequestOptions};
use crate::backend::navigator::{NavigationMethod, Request};
use crate::string::AvmString;
use gc_arena::MutationContext;
@ -102,7 +102,7 @@ fn load<'gc>(
None => return Ok(false.into()),
};
spawn_load_var_fetch(activation, this, &url, None)?;
spawn_load_var_fetch(activation, this, url, None)?;
Ok(true.into())
}
@ -215,7 +215,7 @@ fn send_and_load<'gc>(
.coerce_to_string(activation)?;
let method = NavigationMethod::from_method_str(&method_name).unwrap_or(NavigationMethod::Post);
spawn_load_var_fetch(activation, target, &url, Some((this, method)))?;
spawn_load_var_fetch(activation, target, url, Some((this, method)))?;
Ok(true.into())
}
@ -254,22 +254,21 @@ fn to_string<'gc>(
fn spawn_load_var_fetch<'gc>(
activation: &mut Activation<'_, 'gc, '_>,
loader_object: Object<'gc>,
url: &AvmString,
url: AvmString<'gc>,
send_object: Option<(Object<'gc>, NavigationMethod)>,
) -> Result<Value<'gc>, Error<'gc>> {
let (url, request_options) = if let Some((send_object, method)) = send_object {
let request = if let Some((send_object, method)) = send_object {
// Send properties from `send_object`.
activation.object_into_request_options(send_object, url, Some(method))
activation.object_into_request(send_object, url, Some(method))
} else {
// Not sending any parameters.
(url.to_utf8_lossy(), RequestOptions::get())
Request::get(url.to_utf8_lossy().into_owned())
};
let future = activation.context.load_manager.load_form_into_load_vars(
activation.context.player.clone(),
loader_object,
&url,
request_options,
request,
);
activation.context.navigator.spawn_future(future);

View File

@ -1320,12 +1320,11 @@ fn load_movie<'gc>(
let url = url_val.coerce_to_string(activation)?;
let method = args.get(1).cloned().unwrap_or(Value::Undefined);
let method = NavigationMethod::from_method_str(&method.coerce_to_string(activation)?);
let (url, opts) = activation.locals_into_request_options(&url, method);
let request = activation.locals_into_request(url, method);
let future = activation.context.load_manager.load_movie_into_clip(
activation.context.player.clone(),
DisplayObject::MovieClip(target),
&url,
opts,
request,
None,
None,
);
@ -1343,13 +1342,12 @@ fn load_variables<'gc>(
let url = url_val.coerce_to_string(activation)?;
let method = args.get(1).cloned().unwrap_or(Value::Undefined);
let method = NavigationMethod::from_method_str(&method.coerce_to_string(activation)?);
let (url, opts) = activation.locals_into_request_options(&url, method);
let request = activation.locals_into_request(url, method);
let target = target.object().coerce_to_object(activation);
let future = activation.context.load_manager.load_form_into_object(
activation.context.player.clone(),
target,
&url,
opts,
request,
);
activation.context.navigator.spawn_future(future);

View File

@ -8,7 +8,7 @@ use crate::avm1::object::TObject;
use crate::avm1::property::Attribute;
use crate::avm1::property_decl::{define_properties_on, Declaration};
use crate::avm1::{ArrayObject, Object, Value};
use crate::backend::navigator::RequestOptions;
use crate::backend::navigator::Request;
use crate::display_object::{TDisplayObject, TDisplayObjectContainer};
use gc_arena::MutationContext;
@ -61,8 +61,7 @@ fn load_clip<'gc>(
let future = activation.context.load_manager.load_movie_into_clip(
activation.context.player.clone(),
target,
&url.to_utf8_lossy(),
RequestOptions::get(),
Request::get(url.to_utf8_lossy().into_owned()),
None,
Some(this),
);

View File

@ -7,8 +7,8 @@ use crate::avm1::object::xml_object::XmlObject;
use crate::avm1::property_decl::{define_properties_on, Declaration};
use crate::avm1::{Object, TObject, Value};
use crate::avm_warn;
use crate::backend::navigator::RequestOptions;
use crate::string::WStr;
use crate::backend::navigator::Request;
use crate::string::AvmString;
use crate::xml::{XmlNode, ELEMENT_NODE, TEXT_NODE};
use gc_arena::MutationContext;
@ -134,7 +134,7 @@ fn send_and_load<'gc>(
if let Some(document) = this.as_xml() {
let url = url_val.coerce_to_string(activation)?;
spawn_xml_fetch(activation, this, target, &url, Some(document.as_node()))?;
spawn_xml_fetch(activation, this, target, url, Some(document.as_node()))?;
}
Ok(Value::Undefined)
}
@ -152,7 +152,7 @@ fn load<'gc>(
if let Some(_document) = this.as_xml() {
let url = url_val.coerce_to_string(activation)?;
spawn_xml_fetch(activation, this, this, &url, None)?;
spawn_xml_fetch(activation, this, this, url, None)?;
Ok(true.into())
} else {
@ -252,19 +252,24 @@ fn spawn_xml_fetch<'gc>(
activation: &mut Activation<'_, 'gc, '_>,
this: Object<'gc>,
loader_object: Object<'gc>,
url: &WStr,
url: AvmString<'gc>,
send_object: Option<XmlNode<'gc>>,
) -> Result<Value<'gc>, Error<'gc>> {
let request_options = if let Some(node) = send_object {
let url = url.to_utf8_lossy().into_owned();
let request = if let Some(node) = send_object {
// Send `node` as string.
let string = node.into_string(activation)?;
RequestOptions::post(Some((
Request::post(
url,
Some((
string.to_utf8_lossy().into_owned().into_bytes(),
"application/x-www-form-urlencoded".to_string(),
)))
)),
)
} else {
// Not sending any parameters.
RequestOptions::get()
Request::get(url)
};
this.set("loaded", false.into(), activation)?;
@ -272,8 +277,7 @@ fn spawn_xml_fetch<'gc>(
let future = activation.context.load_manager.load_form_into_load_vars(
activation.context.player.clone(),
loader_object,
&url.to_utf8_lossy(),
request_options,
request,
);
activation.context.navigator.spawn_future(future);

View File

@ -7,7 +7,7 @@ use crate::avm2::names::{Multiname, Namespace, QName};
use crate::avm2::object::TObject;
use crate::avm2::value::Value;
use crate::avm2::{Error, Object};
use crate::backend::navigator::RequestOptions;
use crate::backend::navigator::Request;
use crate::loader::DataFormat;
use gc_arena::{GcCell, MutationContext};
@ -130,14 +130,11 @@ fn spawn_fetch<'gc>(
.get_property(&QName::dynamic_name("url").into(), activation)?
.coerce_to_string(activation)?;
let url = url.to_utf8_lossy();
let future = activation.context.load_manager.load_data_into_url_loader(
activation.context.player.clone(),
loader_object,
&url,
// FIXME - get these from the `URLRequest`
RequestOptions::get(),
Request::get(url.to_utf8_lossy().into_owned()),
data_format,
);
activation.context.navigator.spawn_future(future);

View File

@ -54,8 +54,11 @@ impl NavigationMethod {
}
}
/// Represents request options to be sent as part of a fetch.
pub struct RequestOptions {
/// A fetch request.
pub struct Request {
/// The URL of the request.
url: String,
/// The HTTP method to be used to make the request.
method: NavigationMethod,
@ -66,23 +69,30 @@ pub struct RequestOptions {
body: Option<(Vec<u8>, String)>,
}
impl RequestOptions {
/// Construct request options for a GET request.
pub fn get() -> Self {
impl Request {
/// Construct a GET request.
pub fn get(url: String) -> Self {
Self {
url,
method: NavigationMethod::Get,
body: None,
}
}
/// Construct request options for a POST request.
pub fn post(body: Option<(Vec<u8>, String)>) -> Self {
/// Construct a POST request.
pub fn post(url: String, body: Option<(Vec<u8>, String)>) -> Self {
Self {
url,
method: NavigationMethod::Post,
body,
}
}
/// Retrieve the URL of this request.
pub fn url(&self) -> &str {
&self.url
}
/// Retrieve the navigation method for this request.
pub fn method(&self) -> NavigationMethod {
self.method
@ -138,8 +148,8 @@ pub trait NavigatorBackend {
vars_method: Option<(NavigationMethod, IndexMap<String, String>)>,
);
/// Fetch data at a given URL and return it some time in the future.
fn fetch(&self, url: &str, request_options: RequestOptions) -> OwnedFuture<Response, Error>;
/// Fetch data and return it some time in the future.
fn fetch(&self, request: Request) -> OwnedFuture<Response, Error>;
/// Arrange for a future to be run at some point in the... well, future.
///
@ -280,9 +290,9 @@ impl NavigatorBackend for NullNavigatorBackend {
) {
}
fn fetch(&self, url: &str, _opts: RequestOptions) -> OwnedFuture<Response, Error> {
fn fetch(&self, request: Request) -> OwnedFuture<Response, Error> {
let mut path = self.relative_base_path.clone();
path.push(url);
path.push(request.url);
Box::pin(async move {
let url = Self::url_from_file_path(&path)

View File

@ -11,7 +11,7 @@ use crate::avm2::{
Activation as Avm2Activation, Avm2, Domain as Avm2Domain, Event as Avm2Event,
EventData as Avm2EventData, Object as Avm2Object, QName, Value as Avm2Value,
};
use crate::backend::navigator::{OwnedFuture, RequestOptions};
use crate::backend::navigator::{OwnedFuture, Request};
use crate::backend::render::{determine_jpeg_tag_format, JpegTagFormat};
use crate::context::{ActionQueue, ActionType, UpdateContext};
use crate::display_object::{
@ -189,15 +189,14 @@ impl<'gc> LoadManager<'gc> {
pub fn load_root_movie(
&mut self,
player: Weak<Mutex<Player>>,
url: &str,
options: RequestOptions,
request: Request,
parameters: Vec<(String, String)>,
on_metadata: Box<dyn FnOnce(&swf::HeaderExt)>,
) -> OwnedFuture<(), Error> {
let loader = Loader::RootMovie { self_handle: None };
let handle = self.add_loader(loader);
let loader = self.get_loader_mut(handle).unwrap();
loader.root_movie_loader(player, url.to_owned(), options, parameters, on_metadata)
loader.root_movie_loader(player, request, parameters, on_metadata)
}
/// Kick off a movie clip load.
@ -207,8 +206,7 @@ impl<'gc> LoadManager<'gc> {
&mut self,
player: Weak<Mutex<Player>>,
target_clip: DisplayObject<'gc>,
url: &str,
options: RequestOptions,
request: Request,
loader_url: Option<String>,
target_broadcaster: Option<Object<'gc>>,
) -> OwnedFuture<(), Error> {
@ -220,7 +218,7 @@ impl<'gc> LoadManager<'gc> {
};
let handle = self.add_loader(loader);
let loader = self.get_loader_mut(handle).unwrap();
loader.movie_loader(player, url.to_owned(), options, loader_url)
loader.movie_loader(player, request, loader_url)
}
/// Indicates that a movie clip has initialized (ran its first frame).
@ -247,8 +245,7 @@ impl<'gc> LoadManager<'gc> {
&mut self,
player: Weak<Mutex<Player>>,
target_object: Object<'gc>,
url: &str,
options: RequestOptions,
request: Request,
) -> OwnedFuture<(), Error> {
let loader = Loader::Form {
self_handle: None,
@ -256,7 +253,7 @@ impl<'gc> LoadManager<'gc> {
};
let handle = self.add_loader(loader);
let loader = self.get_loader_mut(handle).unwrap();
loader.form_loader(player, url.to_owned(), options)
loader.form_loader(player, request)
}
/// Kick off a form data load into an AVM1 object.
@ -266,8 +263,7 @@ impl<'gc> LoadManager<'gc> {
&mut self,
player: Weak<Mutex<Player>>,
target_object: Object<'gc>,
url: &str,
options: RequestOptions,
request: Request,
) -> OwnedFuture<(), Error> {
let loader = Loader::LoadVars {
self_handle: None,
@ -275,7 +271,7 @@ impl<'gc> LoadManager<'gc> {
};
let handle = self.add_loader(loader);
let loader = self.get_loader_mut(handle).unwrap();
loader.load_vars_loader(player, url.to_owned(), options)
loader.load_vars_loader(player, request)
}
/// Kick off a data load into a `URLLoader`, updating
@ -286,8 +282,7 @@ impl<'gc> LoadManager<'gc> {
&mut self,
player: Weak<Mutex<Player>>,
target_object: Avm2Object<'gc>,
url: &str,
options: RequestOptions,
request: Request,
data_format: DataFormat,
) -> OwnedFuture<(), Error> {
let loader = Loader::LoadURLLoader {
@ -296,7 +291,7 @@ impl<'gc> LoadManager<'gc> {
};
let handle = self.add_loader(loader);
let loader = self.get_loader_mut(handle).unwrap();
loader.load_url_loader(player, url.to_owned(), options, data_format)
loader.load_url_loader(player, request, data_format)
}
}
@ -390,8 +385,7 @@ impl<'gc> Loader<'gc> {
fn root_movie_loader(
&mut self,
player: Weak<Mutex<Player>>,
url: String,
options: RequestOptions,
request: Request,
parameters: Vec<(String, String)>,
on_metadata: Box<dyn FnOnce(&swf::HeaderExt)>,
) -> OwnedFuture<(), Error> {
@ -407,7 +401,7 @@ impl<'gc> Loader<'gc> {
.expect("Could not upgrade weak reference to player");
Box::pin(async move {
let fetch = player.lock().unwrap().navigator().fetch(&url, options);
let fetch = player.lock().unwrap().navigator().fetch(request);
let response = fetch.await.map_err(|error| {
player
@ -436,8 +430,7 @@ impl<'gc> Loader<'gc> {
fn movie_loader(
&mut self,
player: Weak<Mutex<Player>>,
url: String,
options: RequestOptions,
request: Request,
loader_url: Option<String>,
) -> OwnedFuture<(), Error> {
let handle = match self {
@ -450,7 +443,7 @@ impl<'gc> Loader<'gc> {
.expect("Could not upgrade weak reference to player");
Box::pin(async move {
let fetch = player.lock().unwrap().navigator().fetch(&url, options);
let fetch = player.lock().unwrap().navigator().fetch(request);
let mut replacing_root_movie = false;
player.lock().unwrap().update(|uc| -> Result<(), Error> {
@ -545,8 +538,7 @@ impl<'gc> Loader<'gc> {
fn form_loader(
&mut self,
player: Weak<Mutex<Player>>,
url: String,
options: RequestOptions,
request: Request,
) -> OwnedFuture<(), Error> {
let handle = match self {
Loader::Form { self_handle, .. } => self_handle.expect("Loader not self-introduced"),
@ -558,7 +550,7 @@ impl<'gc> Loader<'gc> {
.expect("Could not upgrade weak reference to player");
Box::pin(async move {
let fetch = player.lock().unwrap().navigator().fetch(&url, options);
let fetch = player.lock().unwrap().navigator().fetch(request);
let response = fetch.await?;
@ -607,8 +599,7 @@ impl<'gc> Loader<'gc> {
fn load_vars_loader(
&mut self,
player: Weak<Mutex<Player>>,
url: String,
options: RequestOptions,
request: Request,
) -> OwnedFuture<(), Error> {
let handle = match self {
Loader::LoadVars { self_handle, .. } => {
@ -622,7 +613,7 @@ impl<'gc> Loader<'gc> {
.expect("Could not upgrade weak reference to player");
Box::pin(async move {
let fetch = player.lock().unwrap().navigator().fetch(&url, options);
let fetch = player.lock().unwrap().navigator().fetch(request);
let data = fetch.await;
@ -689,8 +680,7 @@ impl<'gc> Loader<'gc> {
fn load_url_loader(
&mut self,
player: Weak<Mutex<Player>>,
url: String,
options: RequestOptions,
request: Request,
data_format: DataFormat,
) -> OwnedFuture<(), Error> {
let handle = match self {
@ -705,7 +695,7 @@ impl<'gc> Loader<'gc> {
.expect("Could not upgrade weak reference to player");
Box::pin(async move {
let fetch = player.lock().unwrap().navigator().fetch(&url, options);
let fetch = player.lock().unwrap().navigator().fetch(request);
let response = fetch.await;
player.lock().unwrap().update(|uc| {

View File

@ -8,7 +8,7 @@ use crate::avm2::{Activation as Avm2Activation, Avm2, Domain as Avm2Domain};
use crate::backend::{
audio::{AudioBackend, AudioManager},
log::LogBackend,
navigator::{NavigatorBackend, RequestOptions},
navigator::{NavigatorBackend, Request},
render::RenderBackend,
storage::StorageBackend,
ui::{InputManager, MouseCursor, UiBackend},
@ -242,15 +242,14 @@ impl Player {
/// off.
pub fn fetch_root_movie(
&mut self,
movie_url: &str,
movie_url: String,
parameters: Vec<(String, String)>,
on_metadata: Box<dyn FnOnce(&swf::HeaderExt)>,
) {
self.mutate_with_update_context(|context| {
let future = context.load_manager.load_root_movie(
context.player.clone(),
movie_url,
RequestOptions::get(),
Request::get(movie_url),
parameters,
on_metadata,
);

View File

@ -249,14 +249,14 @@ impl App {
let player = builder.build();
if let Some(movie_url) = &movie_url {
if let Some(movie_url) = movie_url {
let event_loop_proxy = event_loop.create_proxy();
let on_metadata = move |swf_header: &ruffle_core::swf::HeaderExt| {
let _ = event_loop_proxy.send_event(RuffleEvent::OnMetadata(swf_header.clone()));
};
player.lock().unwrap().fetch_root_movie(
movie_url.as_str(),
movie_url.as_str().to_owned(),
parse_parameters(&opt).collect(),
Box::new(on_metadata),
);

View File

@ -1,9 +1,11 @@
//! Navigator backend for web
use crate::custom_event::RuffleEvent;
use isahc::{config::RedirectPolicy, prelude::*, AsyncReadResponseExt, HttpClient, Request};
use isahc::{
config::RedirectPolicy, prelude::*, AsyncReadResponseExt, HttpClient, Request as IsahcRequest,
};
use ruffle_core::backend::navigator::{
NavigationMethod, NavigatorBackend, OwnedFuture, RequestOptions, Response,
NavigationMethod, NavigatorBackend, OwnedFuture, Request, Response,
};
use ruffle_core::indexmap::IndexMap;
use ruffle_core::loader::Error;
@ -103,12 +105,12 @@ impl NavigatorBackend for ExternalNavigatorBackend {
};
}
fn fetch(&self, url: &str, options: RequestOptions) -> OwnedFuture<Response, Error> {
fn fetch(&self, request: Request) -> OwnedFuture<Response, Error> {
// TODO: honor sandbox type (local-with-filesystem, local-with-network, remote, ...)
let full_url = match self.movie_url.join(url) {
let full_url = match self.movie_url.join(request.url()) {
Ok(url) => url,
Err(e) => {
let msg = format!("Invalid URL {}: {}", url, e);
let msg = format!("Invalid URL {}: {}", request.url(), e);
return Box::pin(async move { Err(Error::FetchError(msg)) });
}
};
@ -152,13 +154,13 @@ impl NavigatorBackend for ExternalNavigatorBackend {
let client =
client.ok_or_else(|| Error::FetchError("Network unavailable".to_string()))?;
let request = match options.method() {
NavigationMethod::Get => Request::get(processed_url.to_string()),
NavigationMethod::Post => Request::post(processed_url.to_string()),
let isahc_request = match request.method() {
NavigationMethod::Get => IsahcRequest::get(processed_url.to_string()),
NavigationMethod::Post => IsahcRequest::post(processed_url.to_string()),
};
let (body_data, _) = options.body().clone().unwrap_or_default();
let body = request
let (body_data, _) = request.body().clone().unwrap_or_default();
let body = isahc_request
.body(body_data)
.map_err(|e| Error::FetchError(e.to_string()))?;

View File

@ -219,7 +219,7 @@ impl Ruffle {
/// Stream an arbitrary movie file from (presumably) the Internet.
///
/// This method should only be called once per player.
pub fn stream_from(&mut self, movie_url: &str, parameters: &JsValue) -> Result<(), JsValue> {
pub fn stream_from(&mut self, movie_url: String, parameters: &JsValue) -> Result<(), JsValue> {
let _ = self.with_core_mut(|core| {
let parameters_to_load = parse_movie_parameters(parameters);

View File

@ -1,8 +1,7 @@
//! Navigator backend for web
use js_sys::{Array, ArrayBuffer, Uint8Array};
use ruffle_core::backend::navigator::{
url_from_relative_url, NavigationMethod, NavigatorBackend, OwnedFuture, RequestOptions,
Response,
url_from_relative_url, NavigationMethod, NavigatorBackend, OwnedFuture, Request, Response,
};
use ruffle_core::indexmap::IndexMap;
use ruffle_core::loader::Error;
@ -11,7 +10,8 @@ use url::Url;
use wasm_bindgen::JsCast;
use wasm_bindgen_futures::{spawn_local, JsFuture};
use web_sys::{
window, Blob, BlobPropertyBag, Document, Request, RequestInit, Response as WebResponse,
window, Blob, BlobPropertyBag, Document, Request as WebRequest, RequestInit,
Response as WebResponse,
};
pub struct WebNavigatorBackend {
@ -173,22 +173,22 @@ impl NavigatorBackend for WebNavigatorBackend {
}
}
fn fetch(&self, url: &str, options: RequestOptions) -> OwnedFuture<Response, Error> {
let url = if let Ok(parsed_url) = Url::parse(url) {
fn fetch(&self, request: Request) -> OwnedFuture<Response, Error> {
let url = if let Ok(parsed_url) = Url::parse(request.url()) {
self.pre_process_url(parsed_url).to_string()
} else {
self.resolve_relative_url(url).to_string()
self.resolve_relative_url(request.url()).to_string()
};
Box::pin(async move {
let mut init = RequestInit::new();
init.method(match options.method() {
init.method(match request.method() {
NavigationMethod::Get => "GET",
NavigationMethod::Post => "POST",
});
if let Some((data, mime)) = options.body() {
if let Some((data, mime)) = request.body() {
let arraydata = ArrayBuffer::new(data.len() as u32);
let u8data = Uint8Array::new(&arraydata);
@ -211,7 +211,7 @@ impl NavigatorBackend for WebNavigatorBackend {
init.body(Some(&datablob));
}
let request = Request::new_with_str_and_init(&url, &init)
let request = WebRequest::new_with_str_and_init(&url, &init)
.map_err(|_| Error::FetchError(format!("Unable to create request for {}", url)))?;
let window = web_sys::window().unwrap();