mirror of
https://github.com/leptos-rs/leptos
synced 2024-11-10 06:44:17 +00:00
more docs
This commit is contained in:
parent
0a9cdba22e
commit
15b04a8a85
15 changed files with 221 additions and 55 deletions
|
@ -54,6 +54,7 @@ pub mod browser {
|
|||
}
|
||||
|
||||
#[cfg(any(feature = "reqwest", doc))]
|
||||
/// Implements [`Client`] for a request made by [`reqwest`].
|
||||
pub mod reqwest {
|
||||
use super::Client;
|
||||
use crate::{error::ServerFnError, request::reqwest::CLIENT};
|
||||
|
@ -61,6 +62,7 @@ pub mod reqwest {
|
|||
use reqwest::{Request, Response};
|
||||
use std::future::Future;
|
||||
|
||||
/// Implements [`Client`] for a request made by [`reqwest`].
|
||||
pub struct ReqwestClient;
|
||||
|
||||
impl<CustErr> Client<CustErr> for ReqwestClient {
|
||||
|
|
|
@ -45,15 +45,56 @@ mod multipart;
|
|||
pub use multipart::*;
|
||||
|
||||
mod stream;
|
||||
use crate::{error::ServerFnError, request::ClientReq};
|
||||
use crate::error::ServerFnError;
|
||||
use futures::Future;
|
||||
use http::Method;
|
||||
pub use stream::*;
|
||||
|
||||
/// Deserializes an HTTP request into the data type.
|
||||
/// Serializes a data type into an HTTP request, on the client.
|
||||
///
|
||||
/// Implementations use the methods of the [`ClientReq`](crate::ClientReq) trait to
|
||||
/// convert data into a request body. They are often quite short, usually consisting
|
||||
/// of just two steps:
|
||||
/// 1. Serializing the data into some [`String`], [`Bytes`](bytes::Bytes), or [`Stream`](futures::Stream).
|
||||
/// 2. Creating a request with a body of that type.
|
||||
///
|
||||
/// For example, here’s the implementation for [`Json`].
|
||||
///
|
||||
/// ```rust
|
||||
/// impl<CustErr, T, Request> IntoReq<CustErr, Request, Json> for T
|
||||
/// where
|
||||
/// Request: ClientReq<CustErr>,
|
||||
/// T: Serialize + Send,
|
||||
/// {
|
||||
/// fn into_req(
|
||||
/// self,
|
||||
/// path: &str,
|
||||
/// accepts: &str,
|
||||
/// ) -> Result<Request, ServerFnError<CustErr>> {
|
||||
/// // try to serialize the data
|
||||
/// let data = serde_json::to_string(&self)
|
||||
/// .map_err(|e| ServerFnError::Serialization(e.to_string()))?;
|
||||
/// // and use it as the body of a POST request
|
||||
/// Request::try_new_post(path, accepts, Json::CONTENT_TYPE, data)
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
pub trait IntoReq<CustErr, Request, Encoding> {
|
||||
/// Attempts to serialize the arguments into an HTTP request.
|
||||
fn into_req(
|
||||
self,
|
||||
path: &str,
|
||||
accepts: &str,
|
||||
) -> Result<Request, ServerFnError<CustErr>>;
|
||||
}
|
||||
|
||||
/// Deserializes an HTTP request into the data type, on the server.
|
||||
///
|
||||
/// Implementations use the methods of the [`Req`](crate::Req) trait to access whatever is
|
||||
/// needed from the request.
|
||||
/// needed from the request. They are often quite short, usually consisting
|
||||
/// of just two steps:
|
||||
/// 1. Extracting the request body into some [`String`], [`Bytes`](bytes::Bytes), or [`Stream`](futures::Stream).
|
||||
/// 2. Deserializing that data into the data type.
|
||||
///
|
||||
/// For example, here’s the implementation for [`Json`].
|
||||
///
|
||||
|
@ -80,46 +121,89 @@ pub trait FromReq<CustErr, Request, Encoding>
|
|||
where
|
||||
Self: Sized,
|
||||
{
|
||||
/// Attempts to deserialize the request.
|
||||
/// Attempts to deserialize the arguments from a request.
|
||||
fn from_req(
|
||||
req: Request,
|
||||
) -> impl Future<Output = Result<Self, ServerFnError<CustErr>>> + Send;
|
||||
}
|
||||
|
||||
pub trait IntoReq<CustErr, Request, Encoding> {
|
||||
fn into_req(
|
||||
self,
|
||||
path: &str,
|
||||
accepts: &str,
|
||||
) -> Result<Request, ServerFnError<CustErr>>;
|
||||
}
|
||||
|
||||
pub trait FromRes<CustErr, Response, Encoding>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
fn from_res(
|
||||
res: Response,
|
||||
) -> impl Future<Output = Result<Self, ServerFnError<CustErr>>> + Send;
|
||||
}
|
||||
|
||||
/// Serializes the data type into an HTTP response.
|
||||
///
|
||||
/// Implementations use the methods of the [`Res`](crate::Res) trait to create a
|
||||
/// response. They are often quite short, usually consisting
|
||||
/// of just two steps:
|
||||
/// 1. Serializing the data type to a [`String`], [`Bytes`](bytes::Bytes), or a [`Stream`](futures::Stream).
|
||||
/// 2. Creating a response with that serialized value as its body.
|
||||
///
|
||||
/// For example, here’s the implementation for [`Json`].
|
||||
///
|
||||
/// ```rust
|
||||
/// impl<CustErr, T, Response> IntoRes<CustErr, Response, Json> for T
|
||||
/// where
|
||||
/// Response: Res<CustErr>,
|
||||
/// T: Serialize + Send,
|
||||
/// {
|
||||
/// async fn into_res(self) -> Result<Response, ServerFnError<CustErr>> {
|
||||
/// // try to serialize the data
|
||||
/// let data = serde_json::to_string(&self)
|
||||
/// .map_err(|e| ServerFnError::Serialization(e.to_string()))?;
|
||||
/// // and use it as the body of a response
|
||||
/// Response::try_from_string(Json::CONTENT_TYPE, data)
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
pub trait IntoRes<CustErr, Response, Encoding> {
|
||||
/// Attempts to serialize the output into an HTTP response.
|
||||
fn into_res(
|
||||
self,
|
||||
) -> impl Future<Output = Result<Response, ServerFnError<CustErr>>> + Send;
|
||||
}
|
||||
|
||||
pub trait Encoding {
|
||||
const CONTENT_TYPE: &'static str;
|
||||
const METHOD: Method;
|
||||
}
|
||||
|
||||
pub trait FormDataEncoding<Client, CustErr, Request>
|
||||
/// Deserializes the data type from an HTTP response.
|
||||
///
|
||||
/// Implementations use the methods of the [`ClientRes`](crate::ClientRes) trait to extract
|
||||
/// data from a response. They are often quite short, usually consisting
|
||||
/// of just two steps:
|
||||
/// 1. Extracting a [`String`], [`Bytes`](bytes::Bytes), or a [`Stream`](futures::Stream)
|
||||
/// from the response body.
|
||||
/// 2. Deserializing the data type from that value.
|
||||
///
|
||||
/// For example, here’s the implementation for [`Json`].
|
||||
///
|
||||
/// ```rust
|
||||
/// impl<CustErr, T, Response> FromRes<CustErr, Response, Json> for T
|
||||
/// where
|
||||
/// Response: ClientRes<CustErr> + Send,
|
||||
/// T: DeserializeOwned + Send,
|
||||
/// {
|
||||
/// async fn from_res(
|
||||
/// res: Response,
|
||||
/// ) -> Result<Self, ServerFnError<CustErr>> {
|
||||
/// // extracts the request body
|
||||
/// let data = res.try_into_string().await?;
|
||||
/// // and tries to deserialize it as JSON
|
||||
/// serde_json::from_str(&data)
|
||||
/// .map_err(|e| ServerFnError::Deserialization(e.to_string()))
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
pub trait FromRes<CustErr, Response, Encoding>
|
||||
where
|
||||
Self: Sized,
|
||||
Client: ClientReq<CustErr>,
|
||||
{
|
||||
fn form_data_into_req(
|
||||
form_data: Client::FormData,
|
||||
) -> Result<Self, ServerFnError<CustErr>>;
|
||||
/// Attempts to deserialize the outputs from a response.
|
||||
fn from_res(
|
||||
res: Response,
|
||||
) -> impl Future<Output = Result<Self, ServerFnError<CustErr>>> + Send;
|
||||
}
|
||||
|
||||
/// Defines a particular encoding format, which can be used for serializing or deserializing data.
|
||||
pub trait Encoding {
|
||||
/// The MIME type of the data.
|
||||
const CONTENT_TYPE: &'static str;
|
||||
|
||||
/// The HTTP method used for requests.
|
||||
///
|
||||
/// This should be `POST` in most cases.
|
||||
const METHOD: Method;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,9 @@ use http::Method;
|
|||
use multer::Multipart;
|
||||
use web_sys::FormData;
|
||||
|
||||
/// Encodes multipart form data.
|
||||
///
|
||||
/// You should primarily use this if you are trying to handle file uploads.
|
||||
pub struct MultipartFormData;
|
||||
|
||||
impl Encoding for MultipartFormData {
|
||||
|
@ -16,26 +19,35 @@ impl Encoding for MultipartFormData {
|
|||
const METHOD: Method = Method::POST;
|
||||
}
|
||||
|
||||
/// Describes whether the multipart data is on the client side or the server side.
|
||||
#[derive(Debug)]
|
||||
pub enum MultipartData {
|
||||
/// `FormData` from the browser.
|
||||
Client(BrowserFormData),
|
||||
/// Generic multipart form using [`multer`]. This implements [`Stream`](futures::Stream).
|
||||
Server(multer::Multipart<'static>),
|
||||
}
|
||||
|
||||
impl MultipartData {
|
||||
/// Extracts the inner data to handle as a stream.
|
||||
///
|
||||
/// On the server side, this always returns `Some(_)`. On the client side, always returns `None`.
|
||||
pub fn into_inner(self) -> Option<Multipart<'static>> {
|
||||
match self {
|
||||
MultipartData::Client(_) => None,
|
||||
MultipartData::Server(data) => Some(data),
|
||||
}
|
||||
}
|
||||
|
||||
/// Extracts the inner form data on the client side.
|
||||
///
|
||||
/// On the server side, this always returns `None`. On the client side, always returns `Some(_)`.
|
||||
pub fn into_client_data(self) -> Option<BrowserFormData> {
|
||||
match self {
|
||||
MultipartData::Client(data) => Some(data),
|
||||
MultipartData::Server(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_data(self) -> Option<Multipart<'static>> {
|
||||
match self {
|
||||
MultipartData::Client(_) => None,
|
||||
MultipartData::Server(data) => Some(data),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FormData> for MultipartData {
|
||||
|
|
|
@ -74,7 +74,7 @@ where
|
|||
async fn from_res(res: Response) -> Result<Self, ServerFnError<CustErr>> {
|
||||
let data = res.try_into_string().await?;
|
||||
Self::deserialize(
|
||||
&&serde_json::from_str(&data)
|
||||
&serde_json::from_str(&data)
|
||||
.map_err(|e| ServerFnError::Args(e.to_string()))?,
|
||||
)
|
||||
.map_err(|e| ServerFnError::Deserialization(e.to_string()))
|
||||
|
|
|
@ -9,6 +9,9 @@ use futures::{Stream, StreamExt};
|
|||
use http::Method;
|
||||
use std::pin::Pin;
|
||||
|
||||
/// An encoding that represents a stream of bytes.
|
||||
///
|
||||
/// A server function that uses this as its output encoding should return [`ByteStream`].
|
||||
pub struct Streaming;
|
||||
|
||||
impl Encoding for Streaming {
|
||||
|
@ -36,11 +39,15 @@ where
|
|||
}
|
||||
} */
|
||||
|
||||
/// A stream of bytes.
|
||||
///
|
||||
/// A server function can return this type if its output encoding is [`Streaming`].
|
||||
pub struct ByteStream<CustErr = NoCustomError>(
|
||||
Pin<Box<dyn Stream<Item = Result<Bytes, ServerFnError<CustErr>>> + Send>>,
|
||||
);
|
||||
|
||||
impl<CustErr> ByteStream<CustErr> {
|
||||
/// Consumes the wrapper, returning a stream of bytes.
|
||||
pub fn into_inner(
|
||||
self,
|
||||
) -> impl Stream<Item = Result<Bytes, ServerFnError<CustErr>>> + Send {
|
||||
|
@ -79,6 +86,9 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// An encoding that represents a stream of text.
|
||||
///
|
||||
/// A server function that uses this as its output encoding should return [`TextStream`].
|
||||
pub struct StreamingText;
|
||||
|
||||
impl Encoding for StreamingText {
|
||||
|
@ -86,11 +96,15 @@ impl Encoding for StreamingText {
|
|||
const METHOD: Method = Method::POST;
|
||||
}
|
||||
|
||||
/// A stream of bytes.
|
||||
///
|
||||
/// A server function can return this type if its output encoding is [`StreamingText`].
|
||||
pub struct TextStream<CustErr = NoCustomError>(
|
||||
Pin<Box<dyn Stream<Item = Result<String, ServerFnError<CustErr>>> + Send>>,
|
||||
);
|
||||
|
||||
impl<CustErr> TextStream<CustErr> {
|
||||
/// Consumes the wrapper, returning a stream of text.
|
||||
pub fn into_inner(
|
||||
self,
|
||||
) -> impl Stream<Item = Result<String, ServerFnError<CustErr>>> + Send {
|
||||
|
|
|
@ -75,6 +75,8 @@ impl FromStr for NoCustomError {
|
|||
}
|
||||
}
|
||||
|
||||
/// Wraps some error type, which may implement any of [`Error`], [`Clone`], or
|
||||
/// [`Display`].
|
||||
#[derive(Debug)]
|
||||
pub struct WrapError<T>(pub T);
|
||||
|
||||
|
@ -98,6 +100,7 @@ macro_rules! server_fn_error {
|
|||
/// This trait serves as the conversion method between a variety of types
|
||||
/// and [`ServerFnError`].
|
||||
pub trait ViaError<E> {
|
||||
/// Converts something into an error.
|
||||
fn to_server_error(&self) -> ServerFnError<E>;
|
||||
}
|
||||
|
||||
|
@ -160,6 +163,7 @@ impl<E> ViaError<E> for WrapError<E> {
|
|||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(tag = "type")]
|
||||
pub enum ServerFnError<E = NoCustomError> {
|
||||
/// A user-defined custom error type, which defaults to [`NoCustomError`].
|
||||
WrappedServerError(E),
|
||||
/// Error while trying to register the server function (only occurs in case of poisoned RwLock).
|
||||
Registration(String),
|
||||
|
@ -180,6 +184,7 @@ pub enum ServerFnError<E = NoCustomError> {
|
|||
}
|
||||
|
||||
impl ServerFnError<NoCustomError> {
|
||||
/// Constructs a new [`ServerFnError::ServerError`] from some other type.
|
||||
pub fn new(msg: impl ToString) -> Self {
|
||||
Self::ServerError(msg.to_string())
|
||||
}
|
||||
|
@ -230,9 +235,20 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// A serializable custom server function error type.
|
||||
///
|
||||
/// This is implemented for all types that implement [`FromStr`] + [`Display`].
|
||||
///
|
||||
/// This means you do not necessarily need the overhead of `serde` for a custom error type.
|
||||
/// Instead, you can use something like `strum` to derive `FromStr` and `Display` for your
|
||||
/// custom error type.
|
||||
///
|
||||
/// This is implemented for the default [`ServerFnError`], which uses [`NoCustomError`].
|
||||
pub trait ServerFnErrorSerde: Sized {
|
||||
/// Converts the custom error type to a [`String`].
|
||||
fn ser(&self) -> Result<String, std::fmt::Error>;
|
||||
|
||||
/// Deserializes the custom error type from a [`String`].
|
||||
fn de(data: &str) -> Self;
|
||||
}
|
||||
|
||||
|
@ -327,6 +343,7 @@ where
|
|||
/// it is easy to convert between the two types.
|
||||
#[derive(Error, Debug, Clone)]
|
||||
pub enum ServerFnErrorErr<E = NoCustomError> {
|
||||
/// A user-defined custom error type, which defaults to [`NoCustomError`].
|
||||
#[error("internal error: {0}")]
|
||||
WrappedServerError(E),
|
||||
/// Error while trying to register the server function (only occurs in case of poisoned RwLock).
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#![forbid(unsafe_code)]
|
||||
// uncomment this if you want to feel pain
|
||||
//#![deny(missing_docs)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
//! # Server Functions
|
||||
//!
|
||||
|
|
|
@ -1,18 +1,25 @@
|
|||
use std::{future::Future, pin::Pin};
|
||||
|
||||
/// An abstraction over a middleware layer, which can be used to add additional
|
||||
/// middleware layer to a [`Service`].
|
||||
pub trait Layer<Req, Res>: Send + Sync + 'static {
|
||||
/// Adds this layer to the inner service.
|
||||
fn layer(&self, inner: BoxedService<Req, Res>) -> BoxedService<Req, Res>;
|
||||
}
|
||||
|
||||
/// A type-erased service, which takes an HTTP request and returns a response.
|
||||
pub struct BoxedService<Req, Res>(pub Box<dyn Service<Req, Res> + Send>);
|
||||
|
||||
impl<Req, Res> BoxedService<Req, Res> {
|
||||
/// Constructs a type-erased service from this service.
|
||||
pub fn new(service: impl Service<Req, Res> + Send + 'static) -> Self {
|
||||
Self(Box::new(service))
|
||||
}
|
||||
}
|
||||
|
||||
/// A service converts an HTTP request into a response.
|
||||
pub trait Service<Request, Response> {
|
||||
/// Converts a request into a response.
|
||||
fn run(
|
||||
&mut self,
|
||||
req: Request,
|
||||
|
|
|
@ -5,9 +5,15 @@ use futures::Stream;
|
|||
use send_wrapper::SendWrapper;
|
||||
use std::future::Future;
|
||||
|
||||
/// A wrapped Actix request.
|
||||
///
|
||||
/// This uses a [`SendWrapper`] that allows the Actix `HttpRequest` type to be `Send`, but panics
|
||||
/// if it it is ever sent to another thread. Actix pins request handling to a single thread, so this
|
||||
/// is necessary to be compatible with traits that require `Send` but should never panic in actual use.
|
||||
pub struct ActixRequest(pub(crate) SendWrapper<(HttpRequest, Payload)>);
|
||||
|
||||
impl ActixRequest {
|
||||
/// Returns the raw Actix request, and its body.
|
||||
pub fn take(self) -> (HttpRequest, Payload) {
|
||||
self.0.take()
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ use js_sys::Uint8Array;
|
|||
use send_wrapper::SendWrapper;
|
||||
use web_sys::{FormData, UrlSearchParams};
|
||||
|
||||
/// A `fetch` request made in the browser.
|
||||
#[derive(Debug)]
|
||||
pub struct BrowserRequest(pub(crate) SendWrapper<Request>);
|
||||
|
||||
|
@ -15,6 +16,7 @@ impl From<Request> for BrowserRequest {
|
|||
}
|
||||
}
|
||||
|
||||
/// The `FormData` type available in the browser.
|
||||
#[derive(Debug)]
|
||||
pub struct BrowserFormData(pub(crate) SendWrapper<FormData>);
|
||||
|
||||
|
|
|
@ -3,13 +3,17 @@ use bytes::Bytes;
|
|||
use futures::Stream;
|
||||
use std::future::Future;
|
||||
|
||||
#[cfg(feature = "actix")]
|
||||
/// Request types for Actix.
|
||||
#[cfg(any(feature = "actix", doc))]
|
||||
pub mod actix;
|
||||
#[cfg(feature = "axum")]
|
||||
/// Request types for Axum.
|
||||
#[cfg(any(feature = "axum", doc))]
|
||||
pub mod axum;
|
||||
#[cfg(feature = "browser")]
|
||||
/// Request types for the browser.
|
||||
#[cfg(any(feature = "browser", doc))]
|
||||
pub mod browser;
|
||||
#[cfg(feature = "reqwest")]
|
||||
/// Request types for [`reqwest`].
|
||||
#[cfg(any(feature = "reqwest", doc))]
|
||||
pub mod reqwest;
|
||||
|
||||
/// Represents a request as made by the client.
|
||||
|
@ -17,8 +21,10 @@ pub trait ClientReq<CustErr>
|
|||
where
|
||||
Self: Sized,
|
||||
{
|
||||
/// The type used for URL-encoded form data in this client.
|
||||
type FormData;
|
||||
|
||||
/// Attempts to construct a new `GET` request.
|
||||
fn try_new_get(
|
||||
path: &str,
|
||||
content_type: &str,
|
||||
|
@ -26,6 +32,7 @@ where
|
|||
query: &str,
|
||||
) -> Result<Self, ServerFnError<CustErr>>;
|
||||
|
||||
/// Attempts to construct a new `POST` request with a text body.
|
||||
fn try_new_post(
|
||||
path: &str,
|
||||
content_type: &str,
|
||||
|
@ -33,6 +40,7 @@ where
|
|||
body: String,
|
||||
) -> Result<Self, ServerFnError<CustErr>>;
|
||||
|
||||
/// Attempts to construct a new `POST` request with a binary body.
|
||||
fn try_new_post_bytes(
|
||||
path: &str,
|
||||
content_type: &str,
|
||||
|
@ -40,6 +48,7 @@ where
|
|||
body: Bytes,
|
||||
) -> Result<Self, ServerFnError<CustErr>>;
|
||||
|
||||
/// Attempts to construct a new `POST` request with form data as the body.
|
||||
fn try_new_post_form_data(
|
||||
path: &str,
|
||||
accepts: &str,
|
||||
|
@ -47,6 +56,7 @@ where
|
|||
body: Self::FormData,
|
||||
) -> Result<Self, ServerFnError<CustErr>>;
|
||||
|
||||
/// Attempts to construct a new `POST` request with a multipart body.
|
||||
fn try_new_multipart(
|
||||
path: &str,
|
||||
accepts: &str,
|
||||
|
|
|
@ -95,12 +95,12 @@ impl<CustErr> ClientReq<CustErr> for Request {
|
|||
content_type: &str,
|
||||
body: Self::FormData,
|
||||
) -> Result<Self, ServerFnError<CustErr>> {
|
||||
/*CLIENT
|
||||
.post(path)
|
||||
.header(ACCEPT, accepts)
|
||||
.multipart(body)
|
||||
.build()
|
||||
.map_err(|e| ServerFnError::Request(e.to_string()))*/
|
||||
todo!()
|
||||
CLIENT
|
||||
.post(path)
|
||||
.header(CONTENT_TYPE, content_type)
|
||||
.header(ACCEPT, accepts)
|
||||
.multipart(body)
|
||||
.build()
|
||||
.map_err(|e| ServerFnError::Request(e.to_string()))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,9 +9,15 @@ use futures::{Stream, StreamExt};
|
|||
use send_wrapper::SendWrapper;
|
||||
use std::fmt::{Debug, Display};
|
||||
|
||||
/// A wrapped Actix response.
|
||||
///
|
||||
/// This uses a [`SendWrapper`] that allows the Actix `HttpResponse` type to be `Send`, but panics
|
||||
/// if it it is ever sent to another thread. Actix pins request handling to a single thread, so this
|
||||
/// is necessary to be compatible with traits that require `Send` but should never panic in actual use.
|
||||
pub struct ActixResponse(pub(crate) SendWrapper<HttpResponse>);
|
||||
|
||||
impl ActixResponse {
|
||||
/// Returns the raw Actix response.
|
||||
pub fn take(self) -> HttpResponse {
|
||||
self.0.take()
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ use std::future::Future;
|
|||
use wasm_bindgen::JsCast;
|
||||
use wasm_streams::ReadableStream;
|
||||
|
||||
/// The response to a `fetch` request made in the browser.
|
||||
pub struct BrowserResponse(pub(crate) SendWrapper<Response>);
|
||||
|
||||
impl<CustErr> ClientRes<CustErr> for BrowserResponse {
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
#[cfg(feature = "actix")]
|
||||
/// Response types for Actix.
|
||||
#[cfg(any(feature = "actix", doc))]
|
||||
pub mod actix;
|
||||
#[cfg(feature = "browser")]
|
||||
/// Response types for the browser.
|
||||
#[cfg(any(feature = "browser", doc))]
|
||||
pub mod browser;
|
||||
#[cfg(feature = "axum")]
|
||||
/// Response types for Axum.
|
||||
#[cfg(any(feature = "axum", doc))]
|
||||
pub mod http;
|
||||
#[cfg(feature = "reqwest")]
|
||||
/// Response types for [`reqwest`].
|
||||
#[cfg(any(feature = "reqwest", doc))]
|
||||
pub mod reqwest;
|
||||
|
||||
use crate::error::ServerFnError;
|
||||
|
@ -37,6 +41,7 @@ where
|
|||
+ 'static,
|
||||
) -> Result<Self, ServerFnError<CustErr>>;
|
||||
|
||||
/// Converts an error into a response, with a `500` status code and the error text as its body.
|
||||
fn error_response(err: ServerFnError<CustErr>) -> Self;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue