1#![allow(deprecated)]
2
3use crate::{ContentType, Decodes, Encodes, Format, FormatType};
4use base64::{engine::general_purpose::URL_SAFE, Engine as _};
5use bytes::Bytes;
6use serde::{Deserialize, Serialize};
7use std::{
8 fmt::{self, Display, Write},
9 str::FromStr,
10};
11use throw_error::Error;
12use url::Url;
13
14pub const SERVER_FN_ERROR_HEADER: &str = "serverfnerror";
16
17impl From<ServerFnError> for Error {
18 fn from(e: ServerFnError) -> Self {
19 Error::from(ServerFnErrorWrapper(e))
20 }
21}
22
23#[derive(
26 Debug,
27 Deserialize,
28 Serialize,
29 PartialEq,
30 Eq,
31 Hash,
32 PartialOrd,
33 Ord,
34 Clone,
35 Copy,
36)]
37#[cfg_attr(
38 feature = "rkyv",
39 derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
40)]
41#[deprecated(
42 since = "0.8.0",
43 note = "Now server_fn can return any error type other than ServerFnError, \
44 so the WrappedServerError variant will be removed in 0.9.0"
45)]
46pub struct NoCustomError;
47
48impl fmt::Display for NoCustomError {
50 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
51 write!(f, "Unit Type Displayed")
52 }
53}
54
55impl FromStr for NoCustomError {
56 type Err = ();
57
58 fn from_str(_s: &str) -> Result<Self, Self::Err> {
59 Ok(NoCustomError)
60 }
61}
62
63#[derive(Debug)]
66#[deprecated(
67 since = "0.8.0",
68 note = "Now server_fn can return any error type other than ServerFnError, \
69 so the WrappedServerError variant will be removed in 0.9.0"
70)]
71pub struct WrapError<T>(pub T);
72
73#[macro_export]
76#[deprecated(
77 since = "0.8.0",
78 note = "Now server_fn can return any error type other than ServerFnError, \
79 so the WrappedServerError variant will be removed in 0.9.0"
80)]
81macro_rules! server_fn_error {
82 () => {{
83 use $crate::{ViaError, WrapError};
84 (&&&&&WrapError(())).to_server_error()
85 }};
86 ($err:expr) => {{
87 use $crate::error::{ViaError, WrapError};
88 match $err {
89 error => (&&&&&WrapError(error)).to_server_error(),
90 }
91 }};
92}
93
94#[deprecated(
97 since = "0.8.0",
98 note = "Now server_fn can return any error type other than ServerFnError, \
99 so users should place their custom error type instead of \
100 ServerFnError"
101)]
102pub trait ViaError<E> {
103 fn to_server_error(&self) -> ServerFnError<E>;
105}
106
107impl<E: ServerFnErrorKind + std::error::Error + Clone> ViaError<E>
109 for &&&&WrapError<ServerFnError<E>>
110{
111 fn to_server_error(&self) -> ServerFnError<E> {
112 self.0.clone()
113 }
114}
115
116#[deprecated]
118pub(crate) trait ServerFnErrorKind {}
119
120impl ServerFnErrorKind for ServerFnError {}
121
122impl ViaError<NoCustomError> for &&&WrapError<()> {
124 fn to_server_error(&self) -> ServerFnError {
125 ServerFnError::WrappedServerError(NoCustomError)
126 }
127}
128
129impl<E: std::error::Error + Clone> ViaError<E> for &&WrapError<E> {
132 fn to_server_error(&self) -> ServerFnError<E> {
133 ServerFnError::WrappedServerError(self.0.clone())
134 }
135}
136
137impl<E: Display + Clone> ViaError<E> for &WrapError<E> {
140 fn to_server_error(&self) -> ServerFnError<E> {
141 ServerFnError::ServerError(self.0.to_string())
142 }
143}
144
145impl<E> ViaError<E> for WrapError<E> {
148 #[track_caller]
149 fn to_server_error(&self) -> ServerFnError<E> {
150 panic!(
151 "At {}, you call `to_server_error()` or use `server_fn_error!` \
152 with a value that does not implement `Clone` and either `Error` \
153 or `Display`.",
154 std::panic::Location::caller()
155 );
156 }
157}
158
159#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
166#[cfg_attr(
167 feature = "rkyv",
168 derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
169)]
170pub enum ServerFnError<E = NoCustomError> {
171 #[deprecated(
172 since = "0.8.0",
173 note = "Now server_fn can return any error type other than \
174 ServerFnError, so users should place their custom error type \
175 instead of ServerFnError"
176 )]
177 WrappedServerError(E),
179 Registration(String),
181 Request(String),
183 Response(String),
185 ServerError(String),
187 MiddlewareError(String),
189 Deserialization(String),
191 Serialization(String),
193 Args(String),
195 MissingArg(String),
197}
198
199impl ServerFnError<NoCustomError> {
200 pub fn new(msg: impl ToString) -> Self {
202 Self::ServerError(msg.to_string())
203 }
204}
205
206impl<CustErr> From<CustErr> for ServerFnError<CustErr> {
207 fn from(value: CustErr) -> Self {
208 ServerFnError::WrappedServerError(value)
209 }
210}
211
212impl<E: std::error::Error> From<E> for ServerFnError {
213 fn from(value: E) -> Self {
214 ServerFnError::ServerError(value.to_string())
215 }
216}
217
218impl<CustErr> Display for ServerFnError<CustErr>
219where
220 CustErr: Display,
221{
222 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
223 write!(
224 f,
225 "{}",
226 match self {
227 ServerFnError::Registration(s) => format!(
228 "error while trying to register the server function: {s}"
229 ),
230 ServerFnError::Request(s) => format!(
231 "error reaching server to call server function: {s}"
232 ),
233 ServerFnError::ServerError(s) =>
234 format!("error running server function: {s}"),
235 ServerFnError::MiddlewareError(s) =>
236 format!("error running middleware: {s}"),
237 ServerFnError::Deserialization(s) =>
238 format!("error deserializing server function results: {s}"),
239 ServerFnError::Serialization(s) =>
240 format!("error serializing server function arguments: {s}"),
241 ServerFnError::Args(s) => format!(
242 "error deserializing server function arguments: {s}"
243 ),
244 ServerFnError::MissingArg(s) => format!("missing argument {s}"),
245 ServerFnError::Response(s) =>
246 format!("error generating HTTP response: {s}"),
247 ServerFnError::WrappedServerError(e) => format!("{e}"),
248 }
249 )
250 }
251}
252
253pub struct ServerFnErrorEncoding;
255
256impl ContentType for ServerFnErrorEncoding {
257 const CONTENT_TYPE: &'static str = "text/plain";
258}
259
260impl FormatType for ServerFnErrorEncoding {
261 const FORMAT_TYPE: Format = Format::Text;
262}
263
264impl<CustErr> Encodes<ServerFnError<CustErr>> for ServerFnErrorEncoding
265where
266 CustErr: Display,
267{
268 type Error = std::fmt::Error;
269
270 fn encode(output: &ServerFnError<CustErr>) -> Result<Bytes, Self::Error> {
271 let mut buf = String::new();
272 let result = match output {
273 ServerFnError::WrappedServerError(e) => {
274 write!(&mut buf, "WrappedServerFn|{e}")
275 }
276 ServerFnError::Registration(e) => {
277 write!(&mut buf, "Registration|{e}")
278 }
279 ServerFnError::Request(e) => write!(&mut buf, "Request|{e}"),
280 ServerFnError::Response(e) => write!(&mut buf, "Response|{e}"),
281 ServerFnError::ServerError(e) => {
282 write!(&mut buf, "ServerError|{e}")
283 }
284 ServerFnError::MiddlewareError(e) => {
285 write!(&mut buf, "MiddlewareError|{e}")
286 }
287 ServerFnError::Deserialization(e) => {
288 write!(&mut buf, "Deserialization|{e}")
289 }
290 ServerFnError::Serialization(e) => {
291 write!(&mut buf, "Serialization|{e}")
292 }
293 ServerFnError::Args(e) => write!(&mut buf, "Args|{e}"),
294 ServerFnError::MissingArg(e) => {
295 write!(&mut buf, "MissingArg|{e}")
296 }
297 };
298
299 match result {
300 Ok(()) => Ok(Bytes::from(buf)),
301 Err(e) => Err(e),
302 }
303 }
304}
305
306impl<CustErr> Decodes<ServerFnError<CustErr>> for ServerFnErrorEncoding
307where
308 CustErr: FromStr,
309{
310 type Error = String;
311
312 fn decode(bytes: Bytes) -> Result<ServerFnError<CustErr>, Self::Error> {
313 let data = String::from_utf8(bytes.to_vec())
314 .map_err(|err| format!("UTF-8 conversion error: {err}"))?;
315
316 data.split_once('|')
317 .ok_or_else(|| {
318 format!("Invalid format: missing delimiter in {data:?}")
319 })
320 .and_then(|(ty, data)| match ty {
321 "WrappedServerFn" => CustErr::from_str(data)
322 .map(ServerFnError::WrappedServerError)
323 .map_err(|_| {
324 format!("Failed to parse CustErr from {data:?}")
325 }),
326 "Registration" => {
327 Ok(ServerFnError::Registration(data.to_string()))
328 }
329 "Request" => Ok(ServerFnError::Request(data.to_string())),
330 "Response" => Ok(ServerFnError::Response(data.to_string())),
331 "ServerError" => {
332 Ok(ServerFnError::ServerError(data.to_string()))
333 }
334 "MiddlewareError" => {
335 Ok(ServerFnError::MiddlewareError(data.to_string()))
336 }
337 "Deserialization" => {
338 Ok(ServerFnError::Deserialization(data.to_string()))
339 }
340 "Serialization" => {
341 Ok(ServerFnError::Serialization(data.to_string()))
342 }
343 "Args" => Ok(ServerFnError::Args(data.to_string())),
344 "MissingArg" => Ok(ServerFnError::MissingArg(data.to_string())),
345 _ => Err(format!("Unknown error type: {ty}")),
346 })
347 }
348}
349
350impl<CustErr> FromServerFnError for ServerFnError<CustErr>
351where
352 CustErr: std::fmt::Debug + Display + FromStr + 'static,
353{
354 type Encoder = ServerFnErrorEncoding;
355
356 fn from_server_fn_error(value: ServerFnErrorErr) -> Self {
357 match value {
358 ServerFnErrorErr::Registration(value) => {
359 ServerFnError::Registration(value)
360 }
361 ServerFnErrorErr::Request(value) => ServerFnError::Request(value),
362 ServerFnErrorErr::ServerError(value) => {
363 ServerFnError::ServerError(value)
364 }
365 ServerFnErrorErr::MiddlewareError(value) => {
366 ServerFnError::MiddlewareError(value)
367 }
368 ServerFnErrorErr::Deserialization(value) => {
369 ServerFnError::Deserialization(value)
370 }
371 ServerFnErrorErr::Serialization(value) => {
372 ServerFnError::Serialization(value)
373 }
374 ServerFnErrorErr::Args(value) => ServerFnError::Args(value),
375 ServerFnErrorErr::MissingArg(value) => {
376 ServerFnError::MissingArg(value)
377 }
378 ServerFnErrorErr::Response(value) => ServerFnError::Response(value),
379 ServerFnErrorErr::UnsupportedRequestMethod(value) => {
380 ServerFnError::Request(value)
381 }
382 }
383 }
384}
385
386impl<E> std::error::Error for ServerFnError<E>
387where
388 E: std::error::Error + 'static,
389 ServerFnError<E>: std::fmt::Display,
390{
391 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
392 match self {
393 ServerFnError::WrappedServerError(e) => Some(e),
394 _ => None,
395 }
396 }
397}
398
399#[derive(
401 thiserror::Error, Debug, Clone, PartialEq, Eq, Serialize, Deserialize,
402)]
403#[cfg_attr(
404 feature = "rkyv",
405 derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
406)]
407pub enum ServerFnErrorErr {
408 #[error("error while trying to register the server function: {0}")]
410 Registration(String),
411 #[error("error trying to build `HTTP` method request: {0}")]
413 UnsupportedRequestMethod(String),
414 #[error("error reaching server to call server function: {0}")]
416 Request(String),
417 #[error("error running server function: {0}")]
419 ServerError(String),
420 #[error("error running middleware: {0}")]
422 MiddlewareError(String),
423 #[error("error deserializing server function results: {0}")]
425 Deserialization(String),
426 #[error("error serializing server function arguments: {0}")]
428 Serialization(String),
429 #[error("error deserializing server function arguments: {0}")]
431 Args(String),
432 #[error("missing argument {0}")]
434 MissingArg(String),
435 #[error("error creating response {0}")]
437 Response(String),
438}
439
440#[derive(Debug)]
447pub struct ServerFnUrlError<E> {
448 path: String,
449 error: E,
450}
451
452impl<E: FromServerFnError> ServerFnUrlError<E> {
453 pub fn new(path: impl Display, error: E) -> Self {
456 Self {
457 path: path.to_string(),
458 error,
459 }
460 }
461
462 pub fn error(&self) -> &E {
464 &self.error
465 }
466
467 pub fn path(&self) -> &str {
469 &self.path
470 }
471
472 pub fn to_url(&self, base: &str) -> Result<Url, url::ParseError> {
474 let mut url = Url::parse(base)?;
475 url.query_pairs_mut()
476 .append_pair("__path", &self.path)
477 .append_pair("__err", &URL_SAFE.encode(self.error.ser()));
478 Ok(url)
479 }
480
481 pub fn strip_error_info(path: &mut String) {
484 if let Ok(mut url) = Url::parse(&*path) {
485 let pairs_previously = url
488 .query_pairs()
489 .map(|(k, v)| (k.to_string(), v.to_string()))
490 .collect::<Vec<_>>();
491 let mut pairs = url.query_pairs_mut();
492 pairs.clear();
493 for (key, value) in pairs_previously
494 .into_iter()
495 .filter(|(key, _)| key != "__path" && key != "__err")
496 {
497 pairs.append_pair(&key, &value);
498 }
499 drop(pairs);
500 *path = url.to_string();
501 }
502 }
503
504 pub fn decode_err(err: &str) -> E {
506 let decoded = match URL_SAFE.decode(err) {
507 Ok(decoded) => decoded,
508 Err(err) => {
509 return ServerFnErrorErr::Deserialization(err.to_string())
510 .into_app_error();
511 }
512 };
513 E::de(decoded.into())
514 }
515}
516
517impl<E> From<ServerFnUrlError<E>> for ServerFnError<E> {
518 fn from(error: ServerFnUrlError<E>) -> Self {
519 error.error.into()
520 }
521}
522
523impl<E> From<ServerFnUrlError<ServerFnError<E>>> for ServerFnError<E> {
524 fn from(error: ServerFnUrlError<ServerFnError<E>>) -> Self {
525 error.error
526 }
527}
528
529#[derive(Debug, thiserror::Error)]
530#[doc(hidden)]
531pub struct ServerFnErrorWrapper<E: FromServerFnError>(pub E);
533
534impl<E: FromServerFnError> Display for ServerFnErrorWrapper<E> {
535 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
536 write!(
537 f,
538 "{}",
539 <E::Encoder as FormatType>::into_encoded_string(self.0.ser())
540 )
541 }
542}
543
544impl<E: FromServerFnError> FromStr for ServerFnErrorWrapper<E> {
545 type Err = base64::DecodeError;
546
547 fn from_str(s: &str) -> Result<Self, Self::Err> {
548 let bytes =
549 <E::Encoder as FormatType>::from_encoded_string(s).map_err(|e| {
550 E::from_server_fn_error(ServerFnErrorErr::Deserialization(
551 e.to_string(),
552 ))
553 });
554 let bytes = match bytes {
555 Ok(bytes) => bytes,
556 Err(err) => return Ok(Self(err)),
557 };
558 let err = E::de(bytes);
559 Ok(Self(err))
560 }
561}
562
563pub trait FromServerFnError: std::fmt::Debug + Sized + 'static {
565 type Encoder: Encodes<Self> + Decodes<Self>;
567
568 fn from_server_fn_error(value: ServerFnErrorErr) -> Self;
570
571 fn ser(&self) -> Bytes {
573 Self::Encoder::encode(self).unwrap_or_else(|e| {
574 Self::Encoder::encode(&Self::from_server_fn_error(
575 ServerFnErrorErr::Serialization(e.to_string()),
576 ))
577 .expect(
578 "error serializing should success at least with the \
579 Serialization error",
580 )
581 })
582 }
583
584 fn de(data: Bytes) -> Self {
586 Self::Encoder::decode(data).unwrap_or_else(|e| {
587 ServerFnErrorErr::Deserialization(e.to_string()).into_app_error()
588 })
589 }
590}
591
592pub trait IntoAppError<E> {
594 fn into_app_error(self) -> E;
596}
597
598impl<E> IntoAppError<E> for ServerFnErrorErr
599where
600 E: FromServerFnError,
601{
602 fn into_app_error(self) -> E {
603 E::from_server_fn_error(self)
604 }
605}
606
607#[doc(hidden)]
608#[rustversion::attr(
609 since(1.78),
610 diagnostic::on_unimplemented(
611 message = "{Self} is not a `Result` or aliased `Result`. Server \
612 functions must return a `Result` or aliased `Result`.",
613 label = "Must return a `Result` or aliased `Result`.",
614 note = "If you are trying to return an alias of `Result`, you must \
615 also implement `FromServerFnError` for the error type."
616 )
617)]
618pub trait ServerFnMustReturnResult {
620 type Err;
622 type Ok;
624}
625
626#[doc(hidden)]
627impl<T, E> ServerFnMustReturnResult for Result<T, E> {
628 type Err = E;
629 type Ok = T;
630}
631
632#[test]
633fn assert_from_server_fn_error_impl() {
634 fn assert_impl<T: FromServerFnError>() {}
635
636 assert_impl::<ServerFnError>();
637}