Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wasm build by adding default-client feature gate #591

Merged
merged 3 commits into from
Mar 19, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ jobs:
- run: cargo build --verbose --all-targets
- run: cargo test

wasm-build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: rustup default stable
- run: rustup target add wasm32-unknown-unknown
- run: cargo build --verbose --target=wasm32-unknown-unknown --no-default-features

clippy:
runs-on: ubuntu-latest
steps:
Expand Down
6 changes: 4 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[package]
name = "octocrab"
version = "0.34.1"
resolver = "2"
authors = ["XAMPPRocky <[email protected]>"]
edition = "2018"
readme = "README.md"
Expand Down Expand Up @@ -38,7 +39,7 @@ hyper = "1.1.0"
hyper-rustls = { version = "0.26.0", optional = true }
hyper-timeout = { version = "0.5.1", optional = true }
hyper-tls = { version = "0.6.0", optional = true }
hyper-util = { version = "0.1.3", features = ["client-legacy", "http1"] }
hyper-util = { version = "0.1.3", features = ["http1"] }
once_cell = "1.7.2"
percent-encoding = "2.2.0"
pin-project = "1.0.12"
Expand Down Expand Up @@ -68,7 +69,7 @@ pretty_assertions = "1.4.0"
graphql_client = "0.13.0"

[features]
default = ["follow-redirect", "retry", "rustls", "timeout", "tracing"]
default = ["follow-redirect", "retry", "rustls", "timeout", "tracing", "default-client"]

follow-redirect = ["tower-http/follow-redirect"]
retry = ["tower/retry", "futures-util"]
Expand All @@ -77,3 +78,4 @@ rustls-webpki-tokio = ["hyper-rustls/webpki-tokio"]
opentls = ["hyper-tls"]
stream = ["futures-core", "futures-util"]
timeout = ["hyper-timeout", "tokio", "tower/timeout"]
default-client = ["hyper-util/client-legacy"]
9 changes: 6 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,8 +205,6 @@ use std::sync::{Arc, RwLock};
use std::time::Duration;

use http::{header::HeaderName, StatusCode};
#[cfg(all(not(feature = "opentls"), not(feature = "rustls")))]
use hyper::client::HttpConnector;
use hyper::{Request, Response};

use once_cell::sync::Lazy;
Expand Down Expand Up @@ -265,6 +263,7 @@ pub type Result<T, E = error::Error> = std::result::Result<T, E>;

const GITHUB_BASE_URI: &str = "https://api.github.com";

#[cfg(feature = "default-client")]
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What makes this one incompatible with WASM?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It depends on OctocrabBuilder::default().build(), which is not available on wasm32. Another approach would be having 2 different OctocrabBuilder::default() impls.

I also found another issue with building for wasm: Buffer::new() here depends on tokio. To make it work on wasm I had to changed to Buffer::pair, pass in the executor and spawn the worker task.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think I'd prefer having default client that works on WASM.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I re-checked the code and realized why I didn't go with 2 default impls in the first place: there's currently no good default Svc on wasm. An empty/do-nothing one would be pointless here, since the STATIC_INSTANCE would not work anyway. Bringing in a working Svc for wasm looks like the better option, and reqwest is a great candidate. However it's still using an old version of http seanmonstar/reqwest#2059

I made a half-working implementation using gloo_net, however it involves manually construct gloo_net::Request from http::Request<String>, making the code ugly. Soon after testing a few endpoint, I realize the github rest API would not work for my use case, so had to switch to its graphql API, so I didn't finish the wasm http client tower::Service implementation.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, reqwest is a no go, because it does not support using or getting http::{Request, Response}, reqwest returns its own types and in order to be Sans-IO and client agnostic, octocrab has to support http types, not reqwest types.

static STATIC_INSTANCE: Lazy<arc_swap::ArcSwap<Octocrab>> =
Lazy::new(|| arc_swap::ArcSwap::from_pointee(Octocrab::default()));

Expand Down Expand Up @@ -322,6 +321,7 @@ pub async fn map_github_error(
/// # Ok(())
/// # }
/// ```
#[cfg(feature = "default-client")]
pub fn initialise(crab: Octocrab) -> Arc<Octocrab> {
STATIC_INSTANCE.swap(Arc::from(crab))
}
Expand All @@ -334,6 +334,7 @@ pub fn initialise(crab: Octocrab) -> Arc<Octocrab> {
/// let octocrab = octocrab::instance();
/// }
/// ```
#[cfg(feature = "default-client")]
pub fn instance() -> Arc<Octocrab> {
STATIC_INSTANCE.load().clone()
}
Expand Down Expand Up @@ -590,10 +591,11 @@ impl OctocrabBuilder<NoSvc, DefaultOctocrabBuilderConfig, NoAuth, NotLayerReady>
}

/// Build a [`Client`] instance with the current [`Service`] stack.
#[cfg(feature = "default-client")]
pub fn build(self) -> Result<Octocrab> {
let client: hyper_util::client::legacy::Client<_, String> = {
#[cfg(all(not(feature = "opentls"), not(feature = "rustls")))]
let mut connector = HttpConnector::new();
let mut connector = hyper::client::conn::http1::HttpConnector::new();

#[cfg(all(feature = "rustls", not(feature = "opentls")))]
let connector = {
Expand Down Expand Up @@ -918,6 +920,7 @@ impl fmt::Debug for Octocrab {
/// - `base_uri`: `https://api.github.com`
/// - `auth`: `None`
/// - `client`: http client with the `octocrab` user agent.
#[cfg(feature = "default-client")]
impl Default for Octocrab {
fn default() -> Self {
OctocrabBuilder::default().build().unwrap()
Expand Down
Loading