- Sponsor
-
Notifications
You must be signed in to change notification settings - Fork 690
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Makes the
wasm32-wasip1/2
target a first-class citizen for Leptos's…
… Server-Side (#3063) * feat: WIP wasi integrations crate Signed-off-by: Enzo "raskyld" Nocera <enzo@nocera.eu> * feat(server_fn): add generic types This commit adds `From` implementations for the `Req` and `Res` types using abstraction that are deemed "platform-agnostic". Indeed, both the `http` and `bytes` crates contains types that allows us to represent HTTP Request and Response, while being capable to target unconventional platforms (they even have `no-std` support). This allows the server_fn functions to target new platforms, for example, the `wasm32-wasip*` targets. Signed-off-by: Enzo "raskyld" Nocera <enzo@nocera.eu> * chore(server_fn): generic types cleanup Signed-off-by: Enzo "raskyld" Nocera <enzo@nocera.eu> * feat(integrations/wasi): make WASI a first-class citizen of leptos server-side Signed-off-by: Enzo "raskyld" Nocera <enzo@nocera.eu> * WIP: chore(any_spawner): make the futures::Executor runable Signed-off-by: Enzo "raskyld" Nocera <enzo@nocera.eu> * fix(server_fn): include `generic` in axum. Signed-off-by: Enzo "raskyld" Nocera <enzo@nocera.eu> * chore(any_spawner): some clippy suggestions I ran clippy in really annoying mode since I am still learning Rust and I want to write clean idiomatic code. I took suggestions that I thought made sense, if any maintainers think those are *too much*, I can relax those changes: * Use `core` instead of `std` to ease migration to `no_std` (https://rust-lang.github.io/rust-clippy/master/index.html#/std_instead_of_core) * Add documentation on exported types and statics * Bring some types in, with `use` * Add `#[non_exhaustive]` on types we are not sure we won't extend (https://rust-lang.github.io/rust-clippy/master/index.html#exhaustive_enums) * Add `#[inline]` to help the compiler when doing cross-crate compilation and Link-Time optimization is not enabled. (https://rust-lang.github.io/rust-clippy/master/index.html#/missing_inline_in_public_items) * Use generic types instead of anonymous `impl` params so callers can use the `::<>` turbofish syntax (https://rust-lang.github.io/rust-clippy/master/index.html#/impl_trait_in_params) Signed-off-by: Enzo "raskyld" Nocera <enzo@nocera.eu> * chore(leptos_wasi): fine-tune linter and clean-up Signed-off-by: Enzo "raskyld" Nocera <enzo@nocera.eu> * feat(leptos_wasi): better handling of server fn with form Signed-off-by: Enzo "raskyld" Nocera <enzo@nocera.eu> * chore: cargo fmt Signed-off-by: Enzo "raskyld" Nocera <enzo@nocera.eu> * chore: remove custom clippy Remove clippy crate rules since it seems to make tests fails in tests. Signed-off-by: Enzo "raskyld" Nocera <enzo@nocera.eu> * chore: use `wasi` crate Signed-off-by: Enzo "raskyld" Nocera <enzo@nocera.eu> * chore: revert changes to any_spawner Signed-off-by: Enzo "raskyld" Nocera <enzo@nocera.eu> * chore: simpler crate features + cleanup Signed-off-by: Enzo "raskyld" Nocera <enzo@nocera.eu> * feat(any_spawner): add local custom executor This commit adds a single-thread "local" custom executor, which is useful for environments like `wasm32` targets. Signed-off-by: Enzo "raskyld" Nocera <enzo@nocera.eu> * feat(leptos_wasi): async runtime This commit adds a single-threaded async runtime for `wasm32-wasip*` targets. Signed-off-by: Enzo "raskyld" Nocera <enzo@nocera.eu> * feat(leptos_wasi): error handling This commit adds error types for the users to implement better error handling. Signed-off-by: Enzo "raskyld" Nocera <enzo@nocera.eu> * chore: migrate integration off-tree Signed-off-by: Enzo "raskyld" Nocera <enzo@nocera.eu> * chore(ci): fix formatting Signed-off-by: Enzo "raskyld" Nocera <enzo@nocera.eu> * chore: remove ref to leptos_wasi in Cargo.toml Signed-off-by: Enzo "raskyld" Nocera <enzo@nocera.eu> * chore(ci): fix fmt Signed-off-by: Enzo "raskyld" Nocera <enzo@nocera.eu> * chore(ci): remove explicit into_inter() Signed-off-by: Enzo "raskyld" Nocera <enzo@nocera.eu> * chore(ci): make generic mutually exclusive with other options Signed-off-by: Enzo "raskyld" Nocera <enzo@nocera.eu> --------- Signed-off-by: Enzo "raskyld" Nocera <enzo@nocera.eu>
Showing
10 changed files
with
260 additions
and
5 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
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,74 @@ | ||
//! This module uses platform-agnostic abstractions | ||
//! allowing users to run server functions on a wide range of | ||
//! platforms. | ||
//! | ||
//! The crates in use in this crate are: | ||
//! | ||
//! * `bytes`: platform-agnostic manipulation of bytes. | ||
//! * `http`: low-dependency HTTP abstractions' *front-end*. | ||
//! | ||
//! # Users | ||
//! | ||
//! * `wasm32-wasip*` integration crate `leptos_wasi` is using this | ||
//! crate under the hood. | ||
use crate::request::Req; | ||
use bytes::Bytes; | ||
use futures::{ | ||
stream::{self, Stream}, | ||
StreamExt, | ||
}; | ||
use http::Request; | ||
use std::borrow::Cow; | ||
|
||
impl<CustErr> Req<CustErr> for Request<Bytes> | ||
where | ||
CustErr: 'static, | ||
{ | ||
async fn try_into_bytes( | ||
self, | ||
) -> Result<Bytes, crate::ServerFnError<CustErr>> { | ||
Ok(self.into_body()) | ||
} | ||
|
||
async fn try_into_string( | ||
self, | ||
) -> Result<String, crate::ServerFnError<CustErr>> { | ||
String::from_utf8(self.into_body().into()).map_err(|err| { | ||
crate::ServerFnError::Deserialization(err.to_string()) | ||
}) | ||
} | ||
|
||
fn try_into_stream( | ||
self, | ||
) -> Result< | ||
impl Stream<Item = Result<Bytes, crate::ServerFnError>> + Send + 'static, | ||
crate::ServerFnError<CustErr>, | ||
> { | ||
Ok(stream::iter(self.into_body()) | ||
.ready_chunks(16) | ||
.map(|chunk| Ok(Bytes::from(chunk)))) | ||
} | ||
|
||
fn to_content_type(&self) -> Option<Cow<'_, str>> { | ||
self.headers() | ||
.get(http::header::CONTENT_TYPE) | ||
.map(|val| String::from_utf8_lossy(val.as_bytes())) | ||
} | ||
|
||
fn accepts(&self) -> Option<Cow<'_, str>> { | ||
self.headers() | ||
.get(http::header::ACCEPT) | ||
.map(|val| String::from_utf8_lossy(val.as_bytes())) | ||
} | ||
|
||
fn referer(&self) -> Option<Cow<'_, str>> { | ||
self.headers() | ||
.get(http::header::REFERER) | ||
.map(|val| String::from_utf8_lossy(val.as_bytes())) | ||
} | ||
|
||
fn as_query(&self) -> Option<&str> { | ||
self.uri().query() | ||
} | ||
} |
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,105 @@ | ||
//! This module uses platform-agnostic abstractions | ||
//! allowing users to run server functions on a wide range of | ||
//! platforms. | ||
//! | ||
//! The crates in use in this crate are: | ||
//! | ||
//! * `bytes`: platform-agnostic manipulation of bytes. | ||
//! * `http`: low-dependency HTTP abstractions' *front-end*. | ||
//! | ||
//! # Users | ||
//! | ||
//! * `wasm32-wasip*` integration crate `leptos_wasi` is using this | ||
//! crate under the hood. | ||
use super::Res; | ||
use crate::error::{ | ||
ServerFnError, ServerFnErrorErr, ServerFnErrorSerde, SERVER_FN_ERROR_HEADER, | ||
}; | ||
use bytes::Bytes; | ||
use futures::{Stream, TryStreamExt}; | ||
use http::{header, HeaderValue, Response, StatusCode}; | ||
use std::{ | ||
fmt::{Debug, Display}, | ||
pin::Pin, | ||
str::FromStr, | ||
}; | ||
use throw_error::Error; | ||
|
||
/// The Body of a Response whose *execution model* can be | ||
/// customised using the variants. | ||
pub enum Body { | ||
/// The response body will be written synchronously. | ||
Sync(Bytes), | ||
|
||
/// The response body will be written asynchronously, | ||
/// this execution model is also known as | ||
/// "streaming". | ||
Async(Pin<Box<dyn Stream<Item = Result<Bytes, Error>> + Send + 'static>>), | ||
} | ||
|
||
impl From<String> for Body { | ||
fn from(value: String) -> Self { | ||
Body::Sync(Bytes::from(value)) | ||
} | ||
} | ||
|
||
impl<CustErr> Res<CustErr> for Response<Body> | ||
where | ||
CustErr: Send + Sync + Debug + FromStr + Display + 'static, | ||
{ | ||
fn try_from_string( | ||
content_type: &str, | ||
data: String, | ||
) -> Result<Self, ServerFnError<CustErr>> { | ||
let builder = http::Response::builder(); | ||
builder | ||
.status(200) | ||
.header(http::header::CONTENT_TYPE, content_type) | ||
.body(data.into()) | ||
.map_err(|e| ServerFnError::Response(e.to_string())) | ||
} | ||
|
||
fn try_from_bytes( | ||
content_type: &str, | ||
data: Bytes, | ||
) -> Result<Self, ServerFnError<CustErr>> { | ||
let builder = http::Response::builder(); | ||
builder | ||
.status(200) | ||
.header(http::header::CONTENT_TYPE, content_type) | ||
.body(Body::Sync(data)) | ||
.map_err(|e| ServerFnError::Response(e.to_string())) | ||
} | ||
|
||
fn try_from_stream( | ||
content_type: &str, | ||
data: impl Stream<Item = Result<Bytes, ServerFnError<CustErr>>> | ||
+ Send | ||
+ 'static, | ||
) -> Result<Self, ServerFnError<CustErr>> { | ||
let builder = http::Response::builder(); | ||
builder | ||
.status(200) | ||
.header(http::header::CONTENT_TYPE, content_type) | ||
.body(Body::Async(Box::pin( | ||
data.map_err(ServerFnErrorErr::from).map_err(Error::from), | ||
))) | ||
.map_err(|e| ServerFnError::Response(e.to_string())) | ||
} | ||
|
||
fn error_response(path: &str, err: &ServerFnError<CustErr>) -> Self { | ||
Response::builder() | ||
.status(http::StatusCode::INTERNAL_SERVER_ERROR) | ||
.header(SERVER_FN_ERROR_HEADER, path) | ||
.body(err.ser().unwrap_or_else(|_| err.to_string()).into()) | ||
.unwrap() | ||
} | ||
|
||
fn redirect(&mut self, path: &str) { | ||
if let Ok(path) = HeaderValue::from_str(path) { | ||
self.headers_mut().insert(header::LOCATION, path); | ||
*self.status_mut() = StatusCode::FOUND; | ||
} | ||
} | ||
} |
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 |
---|---|---|
|
@@ -21,6 +21,7 @@ nightly = [] | |
ssr = [] | ||
actix = [] | ||
axum = [] | ||
generic = [] | ||
reqwest = [] | ||
|
||
[package.metadata.docs.rs] | ||
|
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