-
Notifications
You must be signed in to change notification settings - Fork 146
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* WIP * Implement wrapper around fetch API. * Change directory structure * Post merge fixes * Fix some incorrect docs/examples * Actually run CI * Actually run CI part 2 Co-authored-by: Muhammad Hamza <[email protected]>
- Loading branch information
1 parent
07e7dfa
commit 07ad0fc
Showing
8 changed files
with
229 additions
and
37 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,14 +4,15 @@ version = "0.1.0" | |
authors = ["Rust and WebAssembly Working Group", "Muhammad Hamza <[email protected]>"] | ||
edition = "2018" | ||
license = "MIT OR Apache-2.0" | ||
repository = "https://github.com/hamza1311/reqwasm" | ||
repository = "https://github.com/rustwasm/gloo" | ||
description = "HTTP requests library for WASM Apps" | ||
readme = "README.md" | ||
keywords = ["requests", "http", "wasm", "websockets"] | ||
categories = ["wasm", "web-programming::http-client", "api-bindings"] | ||
|
||
[package.metadata.docs.rs] | ||
all-features = true | ||
rustdoc-args = ["--cfg", "docsrs"] | ||
|
||
[dependencies] | ||
wasm-bindgen = "0.2" | ||
|
@@ -62,6 +63,7 @@ http = [ | |
'web-sys/RequestInit', | ||
'web-sys/RequestMode', | ||
'web-sys/Response', | ||
'web-sys/ResponseType', | ||
'web-sys/Window', | ||
'web-sys/RequestCache', | ||
'web-sys/RequestCredentials', | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
use js_sys::{Array, Map}; | ||
use std::fmt; | ||
use wasm_bindgen::{JsCast, JsValue, UnwrapThrowExt}; | ||
|
||
// I experimented with using `js_sys::Object` for the headers, since this object is marked | ||
// experimental in MDN. However it's in the fetch spec, and it's necessary for appending headers. | ||
/// A wrapper around `web_sys::Headers`. | ||
pub struct Headers { | ||
raw: web_sys::Headers, | ||
} | ||
|
||
impl Default for Headers { | ||
fn default() -> Self { | ||
Self::new() | ||
} | ||
} | ||
|
||
impl Headers { | ||
/// Create a new empty headers object. | ||
pub fn new() -> Self { | ||
// pretty sure this will never throw. | ||
Self { | ||
raw: web_sys::Headers::new().unwrap_throw(), | ||
} | ||
} | ||
|
||
/// Build [Headers] from [web_sys::Headers]. | ||
pub fn from_raw(raw: web_sys::Headers) -> Self { | ||
Self { raw } | ||
} | ||
|
||
/// Covert [Headers] to [web_sys::Headers]. | ||
pub fn into_raw(self) -> web_sys::Headers { | ||
self.raw | ||
} | ||
|
||
/// This method appends a new value onto an existing header, or adds the header if it does not | ||
/// already exist. | ||
pub fn append(&self, name: &str, value: &str) { | ||
// XXX Can this throw? WEBIDL says yes, my experiments with forbidden headers and MDN say | ||
// no. | ||
self.raw.append(name, value).unwrap_throw() | ||
} | ||
|
||
/// Deletes a header if it is present. | ||
pub fn delete(&self, name: &str) { | ||
self.raw.delete(name).unwrap_throw() | ||
} | ||
|
||
/// Gets a header if it is present. | ||
pub fn get(&self, name: &str) -> Option<String> { | ||
self.raw.get(name).unwrap_throw() | ||
} | ||
|
||
/// Whether a header with the given name exists. | ||
pub fn has(&self, name: &str) -> bool { | ||
self.raw.has(name).unwrap_throw() | ||
} | ||
|
||
/// Overwrites a header with the given name. | ||
pub fn set(&self, name: &str, value: &str) { | ||
self.raw.set(name, value).unwrap_throw() | ||
} | ||
|
||
/// Iterate over (header name, header value) pairs. | ||
pub fn entries(&self) -> impl Iterator<Item = (String, String)> { | ||
// Here we cheat and cast to a map even though `self` isn't, because the method names match | ||
// and everything works. Is there a better way? Should there be a `MapLike` or | ||
// `MapIterator` type in `js_sys`? | ||
let fake_map: &Map = self.raw.unchecked_ref(); | ||
UncheckedIter(fake_map.entries()).map(|entry| { | ||
let entry: Array = entry.unchecked_into(); | ||
let key = entry.get(0); | ||
let value = entry.get(1); | ||
( | ||
key.as_string().unwrap_throw(), | ||
value.as_string().unwrap_throw(), | ||
) | ||
}) | ||
} | ||
|
||
/// Iterate over the names of the headers. | ||
pub fn keys(&self) -> impl Iterator<Item = String> { | ||
let fake_map: &Map = self.raw.unchecked_ref(); | ||
UncheckedIter(fake_map.keys()).map(|key| key.as_string().unwrap_throw()) | ||
} | ||
|
||
/// Iterate over the values of the headers. | ||
pub fn values(&self) -> impl Iterator<Item = String> { | ||
let fake_map: &Map = self.raw.unchecked_ref(); | ||
UncheckedIter(fake_map.values()).map(|v| v.as_string().unwrap_throw()) | ||
} | ||
} | ||
|
||
impl fmt::Debug for Headers { | ||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
let mut dbg = f.debug_struct("Headers"); | ||
for (key, value) in self.entries() { | ||
dbg.field(&key, &value); | ||
} | ||
dbg.finish() | ||
} | ||
} | ||
|
||
struct UncheckedIter(js_sys::Iterator); | ||
|
||
impl Iterator for UncheckedIter { | ||
type Item = JsValue; | ||
|
||
fn next(&mut self) -> Option<Self::Item> { | ||
// we don't check for errors. Only use this type on things we know conform to the iterator | ||
// interface. | ||
let next = self.0.next().unwrap_throw(); | ||
if next.done() { | ||
None | ||
} else { | ||
Some(next.value()) | ||
} | ||
} | ||
} |
Oops, something went wrong.