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