mirror of
https://github.com/emilk/egui.git
synced 2026-08-30 13:20:05 -04:00
Replace all http code in epi/eframe/egui_glium/egui_web with ehttp (#697)
I've extracted all the http request code and turned it into its own crate at <https://github.com/emilk/ehttp>. There was never a reason for the HTTP request library to be part of `eframe`. Much better to have it as its own crate!
This commit is contained in:
@@ -137,8 +137,6 @@ pub struct AppRunner {
|
||||
prefer_dark_mode: Option<bool>,
|
||||
last_save_time: f64,
|
||||
screen_reader: crate::screen_reader::ScreenReader,
|
||||
#[cfg(feature = "http")]
|
||||
http: Arc<http::WebHttp>,
|
||||
pub(crate) last_text_cursor_pos: Option<egui::Pos2>,
|
||||
}
|
||||
|
||||
@@ -165,8 +163,6 @@ impl AppRunner {
|
||||
prefer_dark_mode,
|
||||
last_save_time: now_sec(),
|
||||
screen_reader: Default::default(),
|
||||
#[cfg(feature = "http")]
|
||||
http: Arc::new(http::WebHttp {}),
|
||||
last_text_cursor_pos: None,
|
||||
};
|
||||
|
||||
@@ -175,8 +171,6 @@ impl AppRunner {
|
||||
let mut frame = epi::backend::FrameBuilder {
|
||||
info: runner.integration_info(),
|
||||
tex_allocator: runner.web_backend.painter.as_tex_allocator(),
|
||||
#[cfg(feature = "http")]
|
||||
http: runner.http.clone(),
|
||||
output: &mut app_output,
|
||||
repaint_signal: runner.needs_repaint.clone(),
|
||||
}
|
||||
@@ -247,8 +241,6 @@ impl AppRunner {
|
||||
let mut frame = epi::backend::FrameBuilder {
|
||||
info: self.integration_info(),
|
||||
tex_allocator: self.web_backend.painter.as_tex_allocator(),
|
||||
#[cfg(feature = "http")]
|
||||
http: self.http.clone(),
|
||||
output: &mut app_output,
|
||||
repaint_signal: self.needs_repaint.clone(),
|
||||
}
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
pub use epi::http::{Request, Response};
|
||||
|
||||
/// NOTE: Ok(..) is returned on network error.
|
||||
/// Err is only for failure to use the fetch api.
|
||||
pub async fn fetch_async(request: &Request) -> Result<Response, String> {
|
||||
fetch_jsvalue(request)
|
||||
.await
|
||||
.map_err(|err| err.as_string().unwrap_or(format!("{:#?}", err)))
|
||||
}
|
||||
|
||||
/// NOTE: Ok(..) is returned on network error.
|
||||
/// Err is only for failure to use the fetch api.
|
||||
async fn fetch_jsvalue(request: &Request) -> Result<Response, JsValue> {
|
||||
// https://rustwasm.github.io/wasm-bindgen/examples/fetch.html
|
||||
// https://github.com/seanmonstar/reqwest/blob/master/src/wasm/client.rs
|
||||
|
||||
use wasm_bindgen::JsCast;
|
||||
use wasm_bindgen_futures::JsFuture;
|
||||
|
||||
let mut opts = web_sys::RequestInit::new();
|
||||
opts.method(&request.method);
|
||||
opts.mode(web_sys::RequestMode::Cors);
|
||||
|
||||
if !request.body.is_empty() {
|
||||
let body_bytes: &[u8] = &request.body;
|
||||
let body_array: js_sys::Uint8Array = body_bytes.into();
|
||||
let js_value: &JsValue = body_array.as_ref();
|
||||
opts.body(Some(js_value));
|
||||
}
|
||||
|
||||
let js_request = web_sys::Request::new_with_str_and_init(&request.url, &opts)?;
|
||||
|
||||
for h in &request.headers {
|
||||
js_request.headers().set(h.0, h.1)?;
|
||||
}
|
||||
|
||||
let window = web_sys::window().unwrap();
|
||||
let response = JsFuture::from(window.fetch_with_request(&js_request)).await?;
|
||||
let response: web_sys::Response = response.dyn_into()?;
|
||||
|
||||
let array_buffer = JsFuture::from(response.array_buffer()?).await?;
|
||||
let uint8_array = js_sys::Uint8Array::new(&array_buffer);
|
||||
let bytes = uint8_array.to_vec();
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/Headers
|
||||
// "Note: When Header values are iterated over, [...] values from duplicate header names are combined."
|
||||
let mut headers = std::collections::BTreeMap::<String, String>::new();
|
||||
let js_headers: web_sys::Headers = response.headers();
|
||||
let js_iter = js_sys::try_iter(&js_headers)
|
||||
.expect("headers try_iter")
|
||||
.expect("headers have an iterator");
|
||||
|
||||
for item in js_iter {
|
||||
let item = item.expect("headers iterator");
|
||||
let array: js_sys::Array = item.into();
|
||||
let v: Vec<JsValue> = array.to_vec();
|
||||
|
||||
let mut key = v[0]
|
||||
.as_string()
|
||||
.ok_or_else(|| JsValue::from_str("headers name"))?;
|
||||
let value = v[1]
|
||||
.as_string()
|
||||
.ok_or_else(|| JsValue::from_str("headers value"))?;
|
||||
|
||||
// for easy lookup
|
||||
key.make_ascii_lowercase();
|
||||
headers.insert(key, value);
|
||||
}
|
||||
|
||||
Ok(Response {
|
||||
url: response.url(),
|
||||
ok: response.ok(),
|
||||
status: response.status(),
|
||||
status_text: response.status_text(),
|
||||
bytes,
|
||||
headers,
|
||||
})
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
pub(crate) struct WebHttp {}
|
||||
|
||||
impl epi::backend::Http for WebHttp {
|
||||
fn fetch_dyn(
|
||||
&self,
|
||||
request: Request,
|
||||
on_done: Box<dyn FnOnce(Result<Response, String>) + Send>,
|
||||
) {
|
||||
crate::spawn_future(async move {
|
||||
let result = crate::http::fetch_async(&request).await;
|
||||
on_done(result)
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -22,8 +22,6 @@
|
||||
#![warn(clippy::all, rust_2018_idioms)]
|
||||
|
||||
pub mod backend;
|
||||
#[cfg(feature = "http")]
|
||||
pub mod http;
|
||||
mod painter;
|
||||
pub mod screen_reader;
|
||||
pub mod webgl1;
|
||||
|
||||
Reference in New Issue
Block a user