Reqwest wasm example (#43)

* Fixed cloudevents sdk to compile with wasm

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>

* Fixed warning

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>

* cargo fmt

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>

* Fixed

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>

* Added cors to actix-web example

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>

* Added reqwest wasm example

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>
This commit is contained in:
Francesco Guardiani 2020-05-20 11:37:55 +02:00 committed by GitHub
parent 2586322a68
commit 594e0a5467
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 6465 additions and 28 deletions

View File

@ -17,6 +17,7 @@ jobs:
target:
- x86_64-unknown-linux-gnu
- x86_64-unknown-linux-musl
- wasm32-unknown-unknown
steps:
- uses: actions/checkout@v2
- run: sudo apt-get update
@ -44,12 +45,22 @@ jobs:
target: ${{ matrix.target }}
override: true
- uses: actions-rs/cargo@v1
if: matrix.target != 'wasm32-unknown-unknown'
with:
command: build
toolchain: ${{ matrix.toolchain }}
args: --target ${{ matrix.target }} --all
- uses: actions-rs/cargo@v1
if: matrix.target != 'wasm32-unknown-unknown'
with:
command: test
toolchain: ${{ matrix.toolchain }}
args: --target ${{ matrix.target }} --all
# If wasm, then we don't need to compile --all
- uses: actions-rs/cargo@v1
if: matrix.target == 'wasm32-unknown-unknown'
with:
command: build
toolchain: ${{ matrix.toolchain }}
args: --target wasm32-unknown-unknown

View File

@ -16,13 +16,19 @@ serde_json = "^1.0"
serde-value = "^0.6"
chrono = { version = "^0.4", features = ["serde"] }
delegate = "^0.4"
uuid = { version = "^0.8", features = ["serde", "v4"] }
hostname = "^0.1"
base64 = "^0.12"
url = { version = "^2.1", features = ["serde"] }
snafu = "^0.6"
lazy_static = "1.4.0"
[target."cfg(not(target_arch = \"wasm32\"))".dependencies]
hostname = "^0.3"
uuid = { version = "^0.8", features = ["v4"] }
[target.'cfg(target_arch = "wasm32")'.dependencies]
web-sys = { version = "^0.3", features = ["Window", "Location"] }
uuid = { version = "^0.8", features = ["v4", "wasm-bindgen"] }
[dev-dependencies]
rstest = "0.6"
claim = "0.3.1"
@ -37,5 +43,6 @@ members = [
"cloudevents-sdk-reqwest"
]
exclude = [
"example-projects/actix-web-example"
"example-projects/actix-web-example",
"example-projects/reqwest-wasm-example"
]

View File

@ -14,4 +14,6 @@ lazy_static = "1.4.0"
bytes = "^0.5"
futures = "^0.3"
serde_json = "^1.0"
[dev-dependencies]
url = { version = "^2.1", features = ["serde"] }

View File

@ -11,7 +11,6 @@ cloudevents-sdk = { path = ".." }
lazy_static = "1.4.0"
bytes = "^0.5"
serde_json = "^1.0"
url = { version = "^2.1", features = ["serde"] }
[dependencies.reqwest]
version = "0.10.4"
@ -20,4 +19,5 @@ features = ["rustls-tls"]
[dev-dependencies]
mockito = "0.25.1"
tokio = { version = "^0.2", features = ["full"] }
tokio = { version = "^0.2", features = ["full"] }
url = { version = "^2.1" }

View File

@ -9,6 +9,7 @@ cloudevents-sdk = { path = "../.." }
cloudevents-sdk-actix-web = { path = "../../cloudevents-sdk-actix-web" }
actix-web = "2"
actix-rt = "1"
actix-cors = "^0.2.0"
lazy_static = "1.4.0"
bytes = "^0.5"
futures = "^0.3"

View File

@ -35,10 +35,11 @@ async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.wrap(actix_web::middleware::Logger::default())
.wrap(actix_cors::Cors::new().finish())
.service(post_event)
.service(get_event)
})
.bind("127.0.0.1:8080")?
.bind("127.0.0.1:9000")?
.workers(1)
.run()
.await

View File

@ -0,0 +1,4 @@
**/node_modules
pkg
*.swp
**/dist

View File

@ -0,0 +1,21 @@
[package]
name = "reqwest-wasm-example"
version = "0.1.0"
authors = ["Francesco Guardiani <francescoguard@gmail.com>"]
edition = "2018"
# Config mostly pulled from: https://github.com/rustwasm/wasm-bindgen/blob/master/examples/fetch/Cargo.toml
[lib]
crate-type = ["cdylib"]
[dependencies]
reqwest = "0.10.4"
cloudevents-sdk = { path = "../.." }
cloudevents-sdk-reqwest = { path = "../../cloudevents-sdk-reqwest" }
url = { version = "^2.1" }
web-sys = { version = "0.3.39", features = ["Window", "Location"] }
wasm-bindgen-futures = "0.4.12"
wasm-bindgen = { version = "0.2.62", features = ["serde-serialize"] }
[workspace]

View File

@ -0,0 +1,13 @@
## Example usage of CLoudEvents sdk/Reqwest from WASM
Install the dependencies with:
npm install
Then build the example locally with:
npm run serve
and then visiting http://localhost:8080 in a browser should run the example!
This example is loosely based off of [this example](https://github.com/rustwasm/wasm-bindgen/blob/master/examples/fetch/src/lib.rs), an example usage of `fetch` from `wasm-bindgen`, and from [reqwest repo](https://github.com/seanmonstar/reqwest/tree/master/examples/wasm_header).

View File

@ -0,0 +1,57 @@
<html>
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type"/>
</head>
<body>
<form class="form-horizontal">
<fieldset>
<!-- Form Name -->
<legend>CloudEvents sender</legend>
<!-- Text input-->
<div class="form-group">
<label class="col-md-4 control-label" for="event_target">Target</label>
<div class="col-md-4">
<input id="event_target" name="event_target" type="text" placeholder="http://localhost:9000" class="form-control input-md" required="">
</div>
</div>
<!-- Text input-->
<div class="form-group">
<label class="col-md-4 control-label" for="event_type">Event Type</label>
<div class="col-md-4">
<input id="event_type" name="event_type" type="text" placeholder="example" class="form-control input-md" required="">
</div>
</div>
<!-- Text input-->
<div class="form-group">
<label class="col-md-4 control-label" for="event_datacontenttype">Event Data Content Type</label>
<div class="col-md-4">
<input id="event_datacontenttype" name="event_datacontenttype" type="text" placeholder="application/json" class="form-control input-md" required="">
</div>
</div>
<!-- Textarea -->
<div class="form-group">
<label class="col-md-4 control-label" for="event_data">Event Data</label>
<div class="col-md-4">
<textarea class="form-control" id="event_data" name="event_data">{"hello":"world"}</textarea>
</div>
</div>
<!-- Button -->
<div class="form-group">
<label class="col-md-4 control-label" for="send">Send Event</label>
<div class="col-md-4">
<button id="send" name="send" class="btn btn-primary" type="button">Send</button>
</div>
</div>
</fieldset>
</form>
</body>
</html>

View File

@ -0,0 +1,17 @@
import $ from 'jquery';
import 'bootstrap/dist/css/bootstrap.min.css';
import 'bootstrap';
import("./pkg").then(rustModule => {
$(document).ready(function () {
$("#send").click(function () {
let target = $("#event_target").val()
let ty = $("#event_type").val()
let dataContentType = $("#event_datacontenttype").val()
let data = $("#event_data").val()
rustModule.run(target, ty, dataContentType, data).catch(console.error);
});
})
}).catch(console.error);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,21 @@
{
"scripts": {
"build": "webpack",
"serve": "webpack-dev-server"
},
"devDependencies": {
"@wasm-tool/wasm-pack-plugin": "^1.3.1",
"css-loader": "^3.5.3",
"html-webpack-plugin": "^3.2.0",
"style-loader": "^1.2.1",
"text-encoding": "^0.7.0",
"webpack": "^4.29.4",
"webpack-cli": "^3.1.1",
"webpack-dev-server": "^3.1.0"
},
"dependencies": {
"bootstrap": "^4.5.0",
"jquery": "^3.5.1",
"popper.js": "^1.16.1"
}
}

View File

@ -0,0 +1,20 @@
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub async fn run(target: String, ty: String, datacontenttype: String, data: String) -> Result<(), String> {
let event = cloudevents::EventBuilder::new()
.ty(ty)
.data(datacontenttype, data)
.build();
println!("Going to send event: {:?}", event);
cloudevents_sdk_reqwest::event_to_request(event, reqwest::Client::new().post(&target))
.map_err(|e| e.to_string())?
.header("Access-Control-Allow-Origin", "*")
.send()
.await
.map_err(|e| e.to_string())?;
Ok(())
}

View File

@ -0,0 +1,39 @@
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
const WasmPackPlugin = require("@wasm-tool/wasm-pack-plugin");
module.exports = {
entry: './index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'index.js',
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: 'index.html'
}),
new WasmPackPlugin({
crateDirectory: path.resolve(__dirname, ".")
}),
// Have this example work in Edge which doesn't ship `TextEncoder` or
// `TextDecoder` at this time.
new webpack.ProvidePlugin({
TextDecoder: ['text-encoding', 'TextDecoder'],
TextEncoder: ['text-encoding', 'TextEncoder']
}),
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
})
],
mode: 'development'
};

View File

@ -193,3 +193,33 @@ impl Attributes {
}
}
}
#[cfg(not(target_arch = "wasm32"))]
pub(crate) fn default_hostname() -> Url {
Url::parse(
format!(
"http://{}",
hostname::get()
.ok()
.map(|s| s.into_string().ok())
.flatten()
.unwrap_or(String::from("localhost".to_string()))
)
.as_ref(),
)
.unwrap()
}
#[cfg(target_arch = "wasm32")]
pub(crate) fn default_hostname() -> Url {
use std::str::FromStr;
Url::from_str(
web_sys::window()
.map(|w| w.location().host().ok())
.flatten()
.unwrap_or(String::from("http://localhost"))
.as_str(),
)
.unwrap()
}

View File

@ -1,8 +1,9 @@
use crate::event::attributes::{AttributeValue, AttributesConverter, DataAttributesWriter};
use crate::event::attributes::{
default_hostname, AttributeValue, AttributesConverter, DataAttributesWriter,
};
use crate::event::AttributesV10;
use crate::event::{AttributesReader, AttributesWriter, SpecVersion};
use chrono::{DateTime, Utc};
use hostname::get_hostname;
use url::Url;
use uuid::Uuid;
@ -153,14 +154,7 @@ impl Default for Attributes {
Attributes {
id: Uuid::new_v4().to_string(),
ty: "type".to_string(),
source: Url::parse(
format!(
"http://{}",
get_hostname().unwrap_or("localhost".to_string())
)
.as_ref(),
)
.unwrap(),
source: default_hostname(),
datacontenttype: None,
schemaurl: None,
subject: None,
@ -193,7 +187,7 @@ mod tests {
use chrono::NaiveDateTime;
#[test]
fn iterator_test_V03() {
fn iterator_test_v03() {
let a = Attributes {
id: String::from("1"),
ty: String::from("someType"),

View File

@ -1,7 +1,8 @@
use crate::event::attributes::{AttributeValue, AttributesConverter, DataAttributesWriter};
use crate::event::attributes::{
default_hostname, AttributeValue, AttributesConverter, DataAttributesWriter,
};
use crate::event::{AttributesReader, AttributesV03, AttributesWriter, SpecVersion};
use chrono::{DateTime, Utc};
use hostname::get_hostname;
use url::Url;
use uuid::Uuid;
@ -152,14 +153,7 @@ impl Default for Attributes {
Attributes {
id: Uuid::new_v4().to_string(),
ty: "type".to_string(),
source: Url::parse(
format!(
"http://{}",
get_hostname().unwrap_or("localhost".to_string())
)
.as_ref(),
)
.unwrap(),
source: default_hostname(),
datacontenttype: None,
dataschema: None,
subject: None,
@ -192,7 +186,7 @@ mod tests {
use chrono::NaiveDateTime;
#[test]
fn iterator_test_V10() {
fn iterator_test_v10() {
let a = Attributes {
id: String::from("1"),
ty: String::from("someType"),