mirror of
https://github.com/yewstack/yew.git
synced 2025-12-08 21:26:25 +00:00
Implement more of FetchOptions (#602)
* Implement more of FetchOptions Add referrer, referrer_policy and integrity * Pass options to Request constructor instead of fetch * Derive Debug on ReferrerPolicy and Referrer * WIP: Add tests * Add tests for referrer and redirect * Add FetchService `integrity` field test * Add FetchService `integrity` field fail test and refactor * Add FetchService `referrer_policy` field tests Co-authored-by: Justin Starry <justin.m.starry@gmail.com>
This commit is contained in:
parent
1ede16795a
commit
12da2b5119
@ -43,6 +43,8 @@ wasm-bindgen = "0.2.58"
|
|||||||
|
|
||||||
[target.'cfg(all(target_arch = "wasm32", not(target_os="wasi"), not(cargo_web)))'.dev-dependencies]
|
[target.'cfg(all(target_arch = "wasm32", not(target_os="wasi"), not(cargo_web)))'.dev-dependencies]
|
||||||
wasm-bindgen-test = "0.3.4"
|
wasm-bindgen-test = "0.3.4"
|
||||||
|
base64 = "0.11.0"
|
||||||
|
ssri = "5.0.0"
|
||||||
|
|
||||||
[target.'cfg(target_os = "emscripten")'.dependencies]
|
[target.'cfg(target_os = "emscripten")'.dependencies]
|
||||||
ryu = "1.0.2" # 1.0.1 breaks emscripten
|
ryu = "1.0.2" # 1.0.1 breaks emscripten
|
||||||
|
|||||||
@ -64,3 +64,71 @@ impl<IN: 'static> Callback<IN> {
|
|||||||
Callback::from(func)
|
Callback::from(func)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
pub(crate) mod test_util {
|
||||||
|
use super::*;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::future::Future;
|
||||||
|
use std::pin::Pin;
|
||||||
|
use std::task::{Context, Poll, Waker};
|
||||||
|
|
||||||
|
struct CallbackHandle<T> {
|
||||||
|
waker: Option<Waker>,
|
||||||
|
output: Option<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Default for CallbackHandle<T> {
|
||||||
|
fn default() -> Self {
|
||||||
|
CallbackHandle {
|
||||||
|
waker: None,
|
||||||
|
output: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) struct CallbackFuture<T>(Rc<RefCell<CallbackHandle<T>>>);
|
||||||
|
|
||||||
|
impl<T> Clone for CallbackFuture<T> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self(self.0.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Default for CallbackFuture<T> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self(Rc::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: 'static> Into<Callback<T>> for CallbackFuture<T> {
|
||||||
|
fn into(self) -> Callback<T> {
|
||||||
|
Callback::from(move |r| self.finish(r))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Future for CallbackFuture<T> {
|
||||||
|
type Output = T;
|
||||||
|
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
|
if let Some(output) = self.ready() {
|
||||||
|
Poll::Ready(output)
|
||||||
|
} else {
|
||||||
|
self.0.borrow_mut().waker = Some(cx.waker().clone());
|
||||||
|
Poll::Pending
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> CallbackFuture<T> {
|
||||||
|
fn ready(&self) -> Option<T> {
|
||||||
|
self.0.borrow_mut().output.take()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finish(&self, output: T) {
|
||||||
|
self.0.borrow_mut().output = Some(output);
|
||||||
|
if let Some(waker) = self.0.borrow_mut().waker.take() {
|
||||||
|
waker.wake();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -71,9 +71,58 @@ pub enum Redirect {
|
|||||||
Manual,
|
Manual,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Type to set referrer for fetch.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Referrer {
|
||||||
|
/// `<same-origin URL>` value of referrer.
|
||||||
|
SameOriginUrl(String),
|
||||||
|
/// `about:client` value of referrer.
|
||||||
|
AboutClient,
|
||||||
|
/// `<empty string>` value of referrer.
|
||||||
|
Empty,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Serialize for Referrer {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: serde::Serializer,
|
||||||
|
{
|
||||||
|
match *self {
|
||||||
|
Referrer::SameOriginUrl(ref s) => serializer.serialize_str(s),
|
||||||
|
Referrer::AboutClient => {
|
||||||
|
serializer.serialize_unit_variant("Referrer", 0, "about:client")
|
||||||
|
}
|
||||||
|
Referrer::Empty => serializer.serialize_unit_variant("Referrer", 1, ""),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Type to set referrer policy for fetch.
|
||||||
|
#[derive(Serialize, Debug)]
|
||||||
|
#[serde(rename_all = "kebab-case")]
|
||||||
|
pub enum ReferrerPolicy {
|
||||||
|
/// `no-referrer` value of referrerPolicy.
|
||||||
|
NoReferrer,
|
||||||
|
/// `no-referrer-when-downgrade` value of referrerPolicy.
|
||||||
|
NoReferrerWhenDowngrade,
|
||||||
|
/// `same-origin` value of referrerPolicy.
|
||||||
|
SameOrigin,
|
||||||
|
/// `origin` value of referrerPolicy.
|
||||||
|
Origin,
|
||||||
|
/// `strict-origin` value of referrerPolicy.
|
||||||
|
StrictOrigin,
|
||||||
|
/// `origin-when-cross-origin` value of referrerPolicy.
|
||||||
|
OriginWhenCrossOrigin,
|
||||||
|
/// `strict-origin-when-cross-origin` value of referrerPolicy.
|
||||||
|
StrictOriginWhenCrossOrigin,
|
||||||
|
/// `unsafe-url` value of referrerPolicy.
|
||||||
|
UnsafeUrl,
|
||||||
|
}
|
||||||
|
|
||||||
/// Init options for `fetch()` function call.
|
/// Init options for `fetch()` function call.
|
||||||
/// https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch
|
/// https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch
|
||||||
#[derive(Serialize, Default, Debug)]
|
#[derive(Serialize, Default, Debug)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct FetchOptions {
|
pub struct FetchOptions {
|
||||||
/// Cache of a fetch request.
|
/// Cache of a fetch request.
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
@ -87,6 +136,15 @@ pub struct FetchOptions {
|
|||||||
/// Request mode of a fetch request.
|
/// Request mode of a fetch request.
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub mode: Option<Mode>,
|
pub mode: Option<Mode>,
|
||||||
|
/// Referrer of a fetch request.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub referrer: Option<Referrer>,
|
||||||
|
/// Referrer policy of a fetch request.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub referrer_policy: Option<ReferrerPolicy>,
|
||||||
|
/// Integrity of a fetch request.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub integrity: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents errors of a fetch service.
|
/// Represents errors of a fetch service.
|
||||||
@ -335,7 +393,12 @@ where
|
|||||||
// Notice that the callback signature must match the call from the javascript
|
// Notice that the callback signature must match the call from the javascript
|
||||||
// side. There is no static check at this point.
|
// side. There is no static check at this point.
|
||||||
let callback = move |success: bool, status: u16, headers: HashMap<String, String>, data: X| {
|
let callback = move |success: bool, status: u16, headers: HashMap<String, String>, data: X| {
|
||||||
let mut response_builder = Response::builder().status(status);
|
let mut response_builder = Response::builder();
|
||||||
|
|
||||||
|
if let Ok(status) = StatusCode::from_u16(status) {
|
||||||
|
response_builder = response_builder.status(status);
|
||||||
|
}
|
||||||
|
|
||||||
for (key, values) in headers {
|
for (key, values) in headers {
|
||||||
response_builder = response_builder.header(key.as_str(), values.as_str());
|
response_builder = response_builder.header(key.as_str(), values.as_str());
|
||||||
}
|
}
|
||||||
@ -357,12 +420,6 @@ where
|
|||||||
if (@{binary} && body != null) {
|
if (@{binary} && body != null) {
|
||||||
body = Uint8Array.from(body);
|
body = Uint8Array.from(body);
|
||||||
}
|
}
|
||||||
var data = {
|
|
||||||
method: @{method},
|
|
||||||
body: body,
|
|
||||||
headers: @{header_map},
|
|
||||||
};
|
|
||||||
var request = new Request(@{uri}, data);
|
|
||||||
var callback = @{callback};
|
var callback = @{callback};
|
||||||
var abortController = AbortController ? new AbortController() : null;
|
var abortController = AbortController ? new AbortController() : null;
|
||||||
var handle = {
|
var handle = {
|
||||||
@ -370,11 +427,19 @@ where
|
|||||||
callback,
|
callback,
|
||||||
abortController,
|
abortController,
|
||||||
};
|
};
|
||||||
var init = @{Serde(options)} || {};
|
var init = {
|
||||||
|
method: @{method},
|
||||||
|
body: body,
|
||||||
|
headers: @{header_map},
|
||||||
|
};
|
||||||
|
var opts = @{Serde(options)} || {};
|
||||||
|
for (var attrname in opts) {
|
||||||
|
init[attrname] = opts[attrname];
|
||||||
|
}
|
||||||
if (abortController && !("signal" in init)) {
|
if (abortController && !("signal" in init)) {
|
||||||
init.signal = abortController.signal;
|
init.signal = abortController.signal;
|
||||||
}
|
}
|
||||||
fetch(request, init).then(function(response) {
|
fetch(@{uri}, init).then(function(response) {
|
||||||
var promise = (@{binary}) ? response.arrayBuffer() : response.text();
|
var promise = (@{binary}) ? response.arrayBuffer() : response.text();
|
||||||
var status = response.status;
|
var status = response.status;
|
||||||
var headers = {};
|
var headers = {};
|
||||||
@ -440,3 +505,272 @@ impl Drop for FetchTask {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[cfg(feature = "wasm_test")]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use crate::callback::test_util::CallbackFuture;
|
||||||
|
use crate::format::{Json, Nothing};
|
||||||
|
use serde::Deserialize;
|
||||||
|
use ssri::Integrity;
|
||||||
|
use wasm_bindgen_test::{wasm_bindgen_test as test, wasm_bindgen_test_configure};
|
||||||
|
|
||||||
|
wasm_bindgen_test_configure!(run_in_browser);
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
struct HttpBin {
|
||||||
|
headers: HashMap<String, String>,
|
||||||
|
origin: String,
|
||||||
|
url: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
struct HttpBinHeaders {
|
||||||
|
headers: HashMap<String, String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
async fn fetch_referrer_default() {
|
||||||
|
let request = Request::get("https://httpbin.org/get")
|
||||||
|
.body(Nothing)
|
||||||
|
.unwrap();
|
||||||
|
let options = FetchOptions::default();
|
||||||
|
let cb_future = CallbackFuture::<Response<Json<Result<HttpBin, anyhow::Error>>>>::default();
|
||||||
|
let callback: Callback<_> = cb_future.clone().into();
|
||||||
|
let _task = FetchService::new().fetch_with_options(request, options, callback);
|
||||||
|
let resp = cb_future.await;
|
||||||
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
|
if let Json(Ok(http_bin)) = resp.body() {
|
||||||
|
assert!(http_bin.headers.get("Referer").is_some());
|
||||||
|
} else {
|
||||||
|
assert!(false, "unexpected resp: {:#?}", resp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
async fn fetch_referrer_same_origin_url() {
|
||||||
|
let request = Request::get("https://httpbin.org/get")
|
||||||
|
.body(Nothing)
|
||||||
|
.unwrap();
|
||||||
|
let options = FetchOptions {
|
||||||
|
referrer: Some(Referrer::SameOriginUrl(String::from("same-origin"))),
|
||||||
|
..FetchOptions::default()
|
||||||
|
};
|
||||||
|
let cb_future = CallbackFuture::<Response<Json<Result<HttpBin, anyhow::Error>>>>::default();
|
||||||
|
let callback: Callback<_> = cb_future.clone().into();
|
||||||
|
let _task = FetchService::new().fetch_with_options(request, options, callback);
|
||||||
|
let resp = cb_future.await;
|
||||||
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
|
if let Json(Ok(http_bin)) = resp.body() {
|
||||||
|
let referrer = http_bin.headers.get("Referer").expect("no referer set");
|
||||||
|
assert!(referrer.ends_with("/same-origin"));
|
||||||
|
} else {
|
||||||
|
assert!(false, "unexpected resp: {:#?}", resp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
async fn fetch_referrer_about_client() {
|
||||||
|
let request = Request::get("https://httpbin.org/get")
|
||||||
|
.body(Nothing)
|
||||||
|
.unwrap();
|
||||||
|
let options = FetchOptions {
|
||||||
|
referrer: Some(Referrer::AboutClient),
|
||||||
|
..FetchOptions::default()
|
||||||
|
};
|
||||||
|
let cb_future = CallbackFuture::<Response<Json<Result<HttpBin, anyhow::Error>>>>::default();
|
||||||
|
let callback: Callback<_> = cb_future.clone().into();
|
||||||
|
let _task = FetchService::new().fetch_with_options(request, options, callback);
|
||||||
|
let resp = cb_future.await;
|
||||||
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
|
if let Json(Ok(http_bin)) = resp.body() {
|
||||||
|
assert!(http_bin.headers.get("Referer").is_some());
|
||||||
|
} else {
|
||||||
|
assert!(false, "unexpected resp: {:#?}", resp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
async fn fetch_referrer_empty() {
|
||||||
|
let request = Request::get("https://httpbin.org/get")
|
||||||
|
.body(Nothing)
|
||||||
|
.unwrap();
|
||||||
|
let options = FetchOptions {
|
||||||
|
referrer: Some(Referrer::Empty),
|
||||||
|
..FetchOptions::default()
|
||||||
|
};
|
||||||
|
let cb_future = CallbackFuture::<Response<Json<Result<HttpBin, anyhow::Error>>>>::default();
|
||||||
|
let callback: Callback<_> = cb_future.clone().into();
|
||||||
|
let _task = FetchService::new().fetch_with_options(request, options, callback);
|
||||||
|
let resp = cb_future.await;
|
||||||
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
|
if let Json(Ok(http_bin)) = resp.body() {
|
||||||
|
assert!(http_bin.headers.get("Referer").is_none());
|
||||||
|
} else {
|
||||||
|
assert!(false, "unexpected resp: {:#?}", resp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
async fn fetch_redirect_default() {
|
||||||
|
let request = Request::get("https://httpbin.org/relative-redirect/1")
|
||||||
|
.body(Nothing)
|
||||||
|
.unwrap();
|
||||||
|
let options = FetchOptions::default();
|
||||||
|
let cb_future = CallbackFuture::<Response<Json<Result<HttpBin, anyhow::Error>>>>::default();
|
||||||
|
let callback: Callback<_> = cb_future.clone().into();
|
||||||
|
let _task = FetchService::new().fetch_with_options(request, options, callback);
|
||||||
|
let resp = cb_future.await;
|
||||||
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
|
if let Json(Ok(http_bin)) = resp.body() {
|
||||||
|
assert_eq!(http_bin.url, String::from("https://httpbin.org/get"));
|
||||||
|
} else {
|
||||||
|
assert!(false, "unexpected resp: {:#?}", resp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
async fn fetch_redirect_follow() {
|
||||||
|
let request = Request::get("https://httpbin.org/relative-redirect/1")
|
||||||
|
.body(Nothing)
|
||||||
|
.unwrap();
|
||||||
|
let options = FetchOptions {
|
||||||
|
redirect: Some(Redirect::Follow),
|
||||||
|
..FetchOptions::default()
|
||||||
|
};
|
||||||
|
let cb_future = CallbackFuture::<Response<Json<Result<HttpBin, anyhow::Error>>>>::default();
|
||||||
|
let callback: Callback<_> = cb_future.clone().into();
|
||||||
|
let _task = FetchService::new().fetch_with_options(request, options, callback);
|
||||||
|
let resp = cb_future.await;
|
||||||
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
|
if let Json(Ok(http_bin)) = resp.body() {
|
||||||
|
assert_eq!(http_bin.url, String::from("https://httpbin.org/get"));
|
||||||
|
} else {
|
||||||
|
assert!(false, "unexpected resp: {:#?}", resp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
async fn fetch_redirect_error() {
|
||||||
|
let request = Request::get("https://httpbin.org/relative-redirect/1")
|
||||||
|
.body(Nothing)
|
||||||
|
.unwrap();
|
||||||
|
let options = FetchOptions {
|
||||||
|
redirect: Some(Redirect::Error),
|
||||||
|
..FetchOptions::default()
|
||||||
|
};
|
||||||
|
let cb_future = CallbackFuture::<Response<Result<String, anyhow::Error>>>::default();
|
||||||
|
let callback: Callback<_> = cb_future.clone().into();
|
||||||
|
let _task = FetchService::new().fetch_with_options(request, options, callback);
|
||||||
|
let resp = cb_future.await;
|
||||||
|
assert_eq!(resp.status(), StatusCode::REQUEST_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
async fn fetch_redirect_manual() {
|
||||||
|
let request = Request::get("https://httpbin.org/relative-redirect/1")
|
||||||
|
.body(Nothing)
|
||||||
|
.unwrap();
|
||||||
|
let options = FetchOptions {
|
||||||
|
redirect: Some(Redirect::Manual),
|
||||||
|
..FetchOptions::default()
|
||||||
|
};
|
||||||
|
let cb_future = CallbackFuture::<Response<Result<String, anyhow::Error>>>::default();
|
||||||
|
let callback: Callback<_> = cb_future.clone().into();
|
||||||
|
let _task = FetchService::new().fetch_with_options(request, options, callback);
|
||||||
|
let resp = cb_future.await;
|
||||||
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
|
// body is empty because the response is opaque for manual redirects
|
||||||
|
assert_eq!(resp.body().as_ref().unwrap(), &String::from(""));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
async fn fetch_integrity() {
|
||||||
|
let resource = "Yew SRI Test";
|
||||||
|
let request = Request::get(format!(
|
||||||
|
"https://httpbin.org/base64/{}",
|
||||||
|
base64::encode_config(resource, base64::URL_SAFE)
|
||||||
|
))
|
||||||
|
.body(Nothing)
|
||||||
|
.unwrap();
|
||||||
|
let options = FetchOptions {
|
||||||
|
integrity: Some(Integrity::from(resource).to_string()),
|
||||||
|
..FetchOptions::default()
|
||||||
|
};
|
||||||
|
let cb_future = CallbackFuture::<Response<Result<String, anyhow::Error>>>::default();
|
||||||
|
let callback: Callback<_> = cb_future.clone().into();
|
||||||
|
let _task = FetchService::new().fetch_with_options(request, options, callback);
|
||||||
|
let resp = cb_future.await;
|
||||||
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
|
assert_eq!(resp.body().as_ref().unwrap(), resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
async fn fetch_integrity_fail() {
|
||||||
|
let resource = "Yew SRI Test";
|
||||||
|
let request = Request::get(format!(
|
||||||
|
"https://httpbin.org/base64/{}",
|
||||||
|
base64::encode_config(resource, base64::URL_SAFE)
|
||||||
|
))
|
||||||
|
.body(Nothing)
|
||||||
|
.unwrap();
|
||||||
|
let options = FetchOptions {
|
||||||
|
integrity: Some(Integrity::from("Yew SRI Test fail").to_string()),
|
||||||
|
..FetchOptions::default()
|
||||||
|
};
|
||||||
|
let cb_future = CallbackFuture::<Response<Result<String, anyhow::Error>>>::default();
|
||||||
|
let callback: Callback<_> = cb_future.clone().into();
|
||||||
|
let _task = FetchService::new().fetch_with_options(request, options, callback);
|
||||||
|
let resp = cb_future.await;
|
||||||
|
assert!(resp.body().is_err());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
async fn fetch_referrer_policy_no_referrer() {
|
||||||
|
let request = Request::get("https://httpbin.org/headers")
|
||||||
|
.body(Nothing)
|
||||||
|
.unwrap();
|
||||||
|
let options = FetchOptions {
|
||||||
|
referrer_policy: Some(ReferrerPolicy::NoReferrer),
|
||||||
|
..FetchOptions::default()
|
||||||
|
};
|
||||||
|
let cb_future =
|
||||||
|
CallbackFuture::<Response<Json<Result<HttpBinHeaders, anyhow::Error>>>>::default();
|
||||||
|
let callback: Callback<_> = cb_future.clone().into();
|
||||||
|
let _task = FetchService::new().fetch_with_options(request, options, callback);
|
||||||
|
let resp = cb_future.await;
|
||||||
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
|
if let Json(Ok(httpbin_headers)) = resp.body() {
|
||||||
|
assert_eq!(httpbin_headers.headers.get("Referer"), None);
|
||||||
|
} else {
|
||||||
|
assert!(false, "unexpected resp: {:#?}", resp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
async fn fetch_referrer_policy_origin() {
|
||||||
|
let request = Request::get("https://httpbin.org/headers")
|
||||||
|
.body(Nothing)
|
||||||
|
.unwrap();
|
||||||
|
let options = FetchOptions {
|
||||||
|
referrer_policy: Some(ReferrerPolicy::Origin),
|
||||||
|
..FetchOptions::default()
|
||||||
|
};
|
||||||
|
let cb_future =
|
||||||
|
CallbackFuture::<Response<Json<Result<HttpBinHeaders, anyhow::Error>>>>::default();
|
||||||
|
let callback: Callback<_> = cb_future.clone().into();
|
||||||
|
let _task = FetchService::new().fetch_with_options(request, options, callback);
|
||||||
|
let resp = cb_future.await;
|
||||||
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
|
if let Json(Ok(httpbin_headers)) = resp.body() {
|
||||||
|
assert!(httpbin_headers
|
||||||
|
.headers
|
||||||
|
.get("Referer")
|
||||||
|
.unwrap()
|
||||||
|
.starts_with(&stdweb::web::window().location().unwrap().origin().unwrap()));
|
||||||
|
} else {
|
||||||
|
assert!(false, "unexpected resp: {:#?}", resp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user