1use bytes::Bytes;
17use conjure_error::{Error, InvalidArgument};
18use futures_core::Stream;
19use http::header::CONTENT_TYPE;
20use http::{
21 request, Extensions, HeaderMap, HeaderValue, Method, Request, Response, StatusCode, Uri,
22};
23use serde::de::DeserializeOwned;
24use serde::Serialize;
25use std::borrow::Cow;
26use std::error;
27use std::future::Future;
28use std::io::Write;
29use std::iter::FromIterator;
30use std::marker::PhantomData;
31use std::pin::Pin;
32use std::str;
33use std::str::FromStr;
34use std::sync::Arc;
35
36use crate::private::{self, SERIALIZABLE_REQUEST_SIZE_LIMIT};
37pub use crate::server::encoding::*;
38#[doc(inline)]
39pub use crate::server::runtime::ConjureRuntime;
40
41pub mod conjure;
42mod encoding;
43pub mod runtime;
44
45pub trait EndpointMetadata {
47 fn method(&self) -> Method;
49
50 fn path(&self) -> &[PathSegment];
54
55 fn template(&self) -> &str;
59
60 fn service_name(&self) -> &str;
62
63 fn name(&self) -> &str;
65
66 fn deprecated(&self) -> Option<&str>;
68}
69
70impl<T> EndpointMetadata for Box<T>
71where
72 T: ?Sized + EndpointMetadata,
73{
74 fn method(&self) -> Method {
75 (**self).method()
76 }
77
78 fn path(&self) -> &[PathSegment] {
79 (**self).path()
80 }
81
82 fn template(&self) -> &str {
83 (**self).template()
84 }
85
86 fn service_name(&self) -> &str {
87 (**self).service_name()
88 }
89
90 fn name(&self) -> &str {
91 (**self).name()
92 }
93
94 fn deprecated(&self) -> Option<&str> {
95 (**self).deprecated()
96 }
97}
98
99pub trait Endpoint<I, O>: EndpointMetadata {
101 fn handle(
111 &self,
112 req: Request<I>,
113 response_extensions: &mut Extensions,
114 ) -> Result<Response<ResponseBody<O>>, Error>;
115}
116
117impl<T, I, O> Endpoint<I, O> for Box<T>
118where
119 T: ?Sized + Endpoint<I, O>,
120{
121 fn handle(
122 &self,
123 req: Request<I>,
124 response_extensions: &mut Extensions,
125 ) -> Result<Response<ResponseBody<O>>, Error> {
126 (**self).handle(req, response_extensions)
127 }
128}
129
130pub trait AsyncEndpoint<I, O>: EndpointMetadata {
132 fn handle(
142 &self,
143 req: Request<I>,
144 response_extensions: &mut Extensions,
145 ) -> impl Future<Output = Result<Response<AsyncResponseBody<O>>, Error>> + Send;
146}
147
148impl<T, I, O> AsyncEndpoint<I, O> for Box<T>
149where
150 T: ?Sized + AsyncEndpoint<I, O>,
151{
152 fn handle(
153 &self,
154 req: Request<I>,
155 response_extensions: &mut Extensions,
156 ) -> impl Future<Output = Result<Response<AsyncResponseBody<O>>, Error>> + Send {
157 (**self).handle(req, response_extensions)
158 }
159}
160
161trait AsyncEndpointEraser<I, O>: EndpointMetadata {
163 #[allow(clippy::type_complexity)]
164 fn handle<'a>(
165 &'a self,
166 req: Request<I>,
167 response_extensions: &'a mut Extensions,
168 ) -> Pin<Box<dyn Future<Output = Result<Response<AsyncResponseBody<O>>, Error>> + Send + 'a>>
169 where
170 I: 'a,
171 O: 'a;
172}
173
174impl<T, I, O> AsyncEndpointEraser<I, O> for T
175where
176 T: AsyncEndpoint<I, O>,
177{
178 fn handle<'a>(
179 &'a self,
180 req: Request<I>,
181 response_extensions: &'a mut Extensions,
182 ) -> Pin<Box<dyn Future<Output = Result<Response<AsyncResponseBody<O>>, Error>> + Send + 'a>>
183 where
184 I: 'a,
185 O: 'a,
186 {
187 Box::pin(self.handle(req, response_extensions))
188 }
189}
190
191pub struct BoxAsyncEndpoint<'a, I, O> {
193 inner: Box<dyn AsyncEndpointEraser<I, O> + 'a + Sync + Send>,
194}
195
196impl<'a, I, O> BoxAsyncEndpoint<'a, I, O> {
197 pub fn new<T>(v: T) -> Self
199 where
200 T: AsyncEndpoint<I, O> + Sync + Send + 'a,
201 {
202 BoxAsyncEndpoint { inner: Box::new(v) }
203 }
204}
205
206impl<I, O> EndpointMetadata for BoxAsyncEndpoint<'_, I, O> {
207 fn method(&self) -> Method {
208 self.inner.method()
209 }
210
211 fn path(&self) -> &[PathSegment] {
212 self.inner.path()
213 }
214
215 fn template(&self) -> &str {
216 self.inner.template()
217 }
218
219 fn service_name(&self) -> &str {
220 self.inner.service_name()
221 }
222
223 fn name(&self) -> &str {
224 self.inner.name()
225 }
226
227 fn deprecated(&self) -> Option<&str> {
228 self.inner.deprecated()
229 }
230}
231
232impl<I, O> AsyncEndpoint<I, O> for BoxAsyncEndpoint<'_, I, O>
233where
234 I: Send,
235{
236 async fn handle(
237 &self,
238 req: Request<I>,
239 response_extensions: &mut Extensions,
240 ) -> Result<Response<AsyncResponseBody<O>>, Error> {
241 self.inner.handle(req, response_extensions).await
242 }
243}
244
245#[derive(Debug, Clone)]
247pub enum PathSegment {
248 Literal(Cow<'static, str>),
250
251 Parameter {
253 name: Cow<'static, str>,
255
256 regex: Option<Cow<'static, str>>,
258 },
259}
260
261pub enum ResponseBody<O> {
263 Empty,
265 Fixed(Bytes),
267 Streaming(Box<dyn WriteBody<O>>),
269}
270
271pub enum AsyncResponseBody<O> {
273 Empty,
275 Fixed(Bytes),
277 Streaming(BoxAsyncWriteBody<'static, O>),
279}
280
281pub trait Service<I, O> {
283 fn endpoints(
285 &self,
286 runtime: &Arc<ConjureRuntime>,
287 ) -> Vec<Box<dyn Endpoint<I, O> + Sync + Send>>;
288}
289
290pub trait AsyncService<I, O> {
292 fn endpoints(&self, runtime: &Arc<ConjureRuntime>) -> Vec<BoxAsyncEndpoint<'static, I, O>>;
294}
295
296pub trait WriteBody<W> {
298 fn write_body(self: Box<Self>, w: &mut W) -> Result<(), Error>;
301}
302
303impl<W> WriteBody<W> for Vec<u8>
304where
305 W: Write,
306{
307 fn write_body(self: Box<Self>, w: &mut W) -> Result<(), Error> {
308 w.write_all(&self).map_err(Error::internal_safe)
309 }
310}
311
312pub trait AsyncWriteBody<W> {
334 fn write_body(self, w: Pin<&mut W>) -> impl Future<Output = Result<(), Error>> + Send;
336}
337
338trait AsyncWriteBodyEraser<W> {
340 fn write_body<'a>(
341 self: Box<Self>,
342 w: Pin<&'a mut W>,
343 ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'a>>
344 where
345 Self: 'a;
346}
347
348impl<T, W> AsyncWriteBodyEraser<W> for T
349where
350 T: AsyncWriteBody<W>,
351{
352 fn write_body<'a>(
353 self: Box<Self>,
354 w: Pin<&'a mut W>,
355 ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'a>>
356 where
357 Self: 'a,
358 {
359 Box::pin((*self).write_body(w))
360 }
361}
362
363pub struct BoxAsyncWriteBody<'a, W> {
365 inner: Box<dyn AsyncWriteBodyEraser<W> + Send + 'a>,
366}
367
368impl<'a, W> BoxAsyncWriteBody<'a, W> {
369 pub fn new<T>(v: T) -> Self
371 where
372 T: AsyncWriteBody<W> + Send + 'a,
373 {
374 BoxAsyncWriteBody { inner: Box::new(v) }
375 }
376}
377
378impl<W> AsyncWriteBody<W> for BoxAsyncWriteBody<'_, W>
379where
380 W: Send,
381{
382 async fn write_body(self, w: Pin<&mut W>) -> Result<(), Error>
383 where
384 W: Send,
385 {
386 self.inner.write_body(w).await
387 }
388}
389
390pub struct RequestContext<'a> {
395 request_parts: &'a request::Parts,
396 response_extensions: &'a mut Extensions,
397}
398
399impl<'a> RequestContext<'a> {
400 #[doc(hidden)]
401 #[inline]
402 pub fn new(request_parts: &'a request::Parts, response_extensions: &'a mut Extensions) -> Self {
403 RequestContext {
404 request_parts,
405 response_extensions,
406 }
407 }
408
409 #[inline]
411 pub fn request_uri(&self) -> &Uri {
412 &self.request_parts.uri
413 }
414
415 #[inline]
417 pub fn request_headers(&self) -> &HeaderMap {
418 &self.request_parts.headers
419 }
420
421 #[inline]
423 pub fn request_extensions(&self) -> &Extensions {
424 &self.request_parts.extensions
425 }
426
427 #[inline]
429 pub fn response_extensions(&self) -> &Extensions {
430 self.response_extensions
431 }
432
433 #[inline]
435 pub fn response_extensions_mut(&mut self) -> &mut Extensions {
436 self.response_extensions
437 }
438}
439
440#[derive(Copy, Clone, Debug)]
446pub struct UseLegacyErrorSerialization;
447
448pub trait DeserializeRequest<T, R> {
451 fn deserialize(runtime: &ConjureRuntime, headers: &HeaderMap, body: R) -> Result<T, Error>;
453}
454
455pub trait AsyncDeserializeRequest<T, R> {
458 fn deserialize(
460 runtime: &ConjureRuntime,
461 headers: &HeaderMap,
462 body: R,
463 ) -> impl Future<Output = Result<T, Error>> + Send;
464}
465
466pub enum StdRequestDeserializer<const N: usize = { SERIALIZABLE_REQUEST_SIZE_LIMIT }> {}
471
472impl<const N: usize, T, R> DeserializeRequest<T, R> for StdRequestDeserializer<N>
473where
474 T: DeserializeOwned,
475 R: Iterator<Item = Result<Bytes, Error>>,
476{
477 fn deserialize(runtime: &ConjureRuntime, headers: &HeaderMap, body: R) -> Result<T, Error> {
478 let encoding = runtime.request_body_encoding(headers)?;
479 let buf = private::read_body(body, Some(N))?;
480 let v = T::deserialize(encoding.deserializer(&buf).deserializer())
481 .map_err(|e| Error::service(e, InvalidArgument::new()))?;
482 Ok(v)
483 }
484}
485
486impl<const N: usize, T, R> AsyncDeserializeRequest<T, R> for StdRequestDeserializer<N>
487where
488 T: DeserializeOwned,
489 R: Stream<Item = Result<Bytes, Error>> + Send,
490{
491 async fn deserialize(
492 runtime: &ConjureRuntime,
493 headers: &HeaderMap,
494 body: R,
495 ) -> Result<T, Error> {
496 let encoding = runtime.request_body_encoding(headers)?;
497 let buf = private::async_read_body(body, Some(N)).await?;
498 let v = T::deserialize(encoding.deserializer(&buf).deserializer())
499 .map_err(|e| Error::service(e, InvalidArgument::new()))?;
500 Ok(v)
501 }
502}
503
504pub struct FromRequestDeserializer<D, U> {
506 _p: PhantomData<(D, U)>,
507}
508
509impl<T, R, D, U> DeserializeRequest<T, R> for FromRequestDeserializer<D, U>
510where
511 T: From<U>,
512 D: DeserializeRequest<U, R>,
513{
514 fn deserialize(runtime: &ConjureRuntime, headers: &HeaderMap, body: R) -> Result<T, Error> {
515 D::deserialize(runtime, headers, body).map(From::from)
516 }
517}
518
519impl<T, R, D, U> AsyncDeserializeRequest<T, R> for FromRequestDeserializer<D, U>
520where
521 T: From<U>,
522 D: AsyncDeserializeRequest<U, R>,
523 R: Send,
524{
525 async fn deserialize(
526 runtime: &ConjureRuntime,
527 headers: &HeaderMap,
528 body: R,
529 ) -> Result<T, Error> {
530 D::deserialize(runtime, headers, body).await.map(From::from)
531 }
532}
533
534pub trait SerializeResponse<T, W> {
536 fn serialize(
538 runtime: &ConjureRuntime,
539 request_headers: &HeaderMap,
540 value: T,
541 ) -> Result<Response<ResponseBody<W>>, Error>;
542}
543
544pub trait AsyncSerializeResponse<T, W> {
547 fn serialize(
549 runtime: &ConjureRuntime,
550 request_headers: &HeaderMap,
551 value: T,
552 ) -> Result<Response<AsyncResponseBody<W>>, Error>;
553}
554
555pub enum EmptyResponseSerializer {}
557
558impl EmptyResponseSerializer {
559 fn serialize_inner<T>(body: T) -> Result<Response<T>, Error> {
560 let mut response = Response::new(body);
561 *response.status_mut() = StatusCode::NO_CONTENT;
562 Ok(response)
563 }
564}
565
566impl<W> SerializeResponse<(), W> for EmptyResponseSerializer {
567 fn serialize(
568 _: &ConjureRuntime,
569 _: &HeaderMap,
570 _: (),
571 ) -> Result<Response<ResponseBody<W>>, Error> {
572 Self::serialize_inner(ResponseBody::Empty)
573 }
574}
575
576impl<W> AsyncSerializeResponse<(), W> for EmptyResponseSerializer {
577 fn serialize(
578 _: &ConjureRuntime,
579 _: &HeaderMap,
580 _: (),
581 ) -> Result<Response<AsyncResponseBody<W>>, Error> {
582 Self::serialize_inner(AsyncResponseBody::Empty)
583 }
584}
585
586pub enum StdResponseSerializer {}
588
589impl StdResponseSerializer {
590 fn serialize_inner<B>(
591 runtime: &ConjureRuntime,
592 request_headers: &HeaderMap,
593 value: &dyn erased_serde::Serialize,
594 make_body: impl FnOnce(Bytes) -> B,
595 ) -> Result<Response<B>, Error> {
596 let encoding = runtime.response_body_encoding(request_headers)?;
597
598 let mut body = vec![];
599 value
600 .erased_serialize(&mut *encoding.serializer(&mut body).serializer())
601 .map_err(Error::internal)?;
602
603 let mut response = Response::new(make_body(body.into()));
604 response
605 .headers_mut()
606 .insert(CONTENT_TYPE, encoding.content_type());
607
608 Ok(response)
609 }
610}
611
612impl<T, W> SerializeResponse<T, W> for StdResponseSerializer
613where
614 T: Serialize,
615{
616 fn serialize(
617 runtime: &ConjureRuntime,
618 request_headers: &HeaderMap,
619 value: T,
620 ) -> Result<Response<ResponseBody<W>>, Error> {
621 Self::serialize_inner(runtime, request_headers, &value, ResponseBody::Fixed)
622 }
623}
624
625impl<T, W> AsyncSerializeResponse<T, W> for StdResponseSerializer
626where
627 T: Serialize,
628{
629 fn serialize(
630 runtime: &ConjureRuntime,
631 request_headers: &HeaderMap,
632 value: T,
633 ) -> Result<Response<AsyncResponseBody<W>>, Error> {
634 Self::serialize_inner(runtime, request_headers, &value, AsyncResponseBody::Fixed)
635 }
636}
637
638pub trait DecodeHeader<T> {
640 fn decode<'a, I>(runtime: &ConjureRuntime, headers: I) -> Result<T, Error>
642 where
643 I: IntoIterator<Item = &'a HeaderValue>;
644}
645
646pub trait DecodeParam<T> {
649 fn decode<I>(runtime: &ConjureRuntime, params: I) -> Result<T, Error>
653 where
654 I: IntoIterator,
655 I::Item: AsRef<str>;
656}
657
658pub enum FromStrDecoder {}
660
661impl<T> DecodeHeader<T> for FromStrDecoder
662where
663 T: FromStr,
664 T::Err: Into<Box<dyn error::Error + Sync + Send>>,
665{
666 fn decode<'a, I>(_: &ConjureRuntime, headers: I) -> Result<T, Error>
667 where
668 I: IntoIterator<Item = &'a HeaderValue>,
669 {
670 only_item(headers)?
671 .to_str()
672 .map_err(|e| Error::service(e, InvalidArgument::new()))?
673 .parse()
674 .map_err(|e| Error::service(e, InvalidArgument::new()))
675 }
676}
677
678impl<T> DecodeParam<T> for FromStrDecoder
679where
680 T: FromStr,
681 T::Err: Into<Box<dyn error::Error + Sync + Send>>,
682{
683 fn decode<I>(_: &ConjureRuntime, params: I) -> Result<T, Error>
684 where
685 I: IntoIterator,
686 I::Item: AsRef<str>,
687 {
688 only_item(params)?
689 .as_ref()
690 .parse()
691 .map_err(|e| Error::service(e, InvalidArgument::new()))
692 }
693}
694
695pub enum FromStrOptionDecoder {}
697
698impl<T> DecodeHeader<Option<T>> for FromStrOptionDecoder
699where
700 T: FromStr,
701 T::Err: Into<Box<dyn error::Error + Sync + Send>>,
702{
703 fn decode<'a, I>(_: &ConjureRuntime, headers: I) -> Result<Option<T>, Error>
704 where
705 I: IntoIterator<Item = &'a HeaderValue>,
706 {
707 let Some(header) = optional_item(headers)? else {
708 return Ok(None);
709 };
710 let value = header
711 .to_str()
712 .map_err(|e| Error::service(e, InvalidArgument::new()))?
713 .parse()
714 .map_err(|e| Error::service(e, InvalidArgument::new()))?;
715 Ok(Some(value))
716 }
717}
718
719impl<T> DecodeParam<Option<T>> for FromStrOptionDecoder
720where
721 T: FromStr,
722 T::Err: Into<Box<dyn error::Error + Sync + Send>>,
723{
724 fn decode<I>(_: &ConjureRuntime, params: I) -> Result<Option<T>, Error>
725 where
726 I: IntoIterator,
727 I::Item: AsRef<str>,
728 {
729 let Some(param) = optional_item(params)? else {
730 return Ok(None);
731 };
732 let value = param
733 .as_ref()
734 .parse()
735 .map_err(|e| Error::service(e, InvalidArgument::new()))?;
736 Ok(Some(value))
737 }
738}
739
740fn optional_item<I>(it: I) -> Result<Option<I::Item>, Error>
741where
742 I: IntoIterator,
743{
744 let mut it = it.into_iter();
745 let Some(item) = it.next() else {
746 return Ok(None);
747 };
748
749 let remaining = it.count();
750 if remaining > 0 {
751 return Err(
752 Error::service_safe("expected at most 1 parameter", InvalidArgument::new())
753 .with_safe_param("actual", remaining + 1),
754 );
755 }
756
757 Ok(Some(item))
758}
759
760pub struct FromStrSeqDecoder<U> {
763 _p: PhantomData<U>,
764}
765
766impl<T, U> DecodeParam<T> for FromStrSeqDecoder<U>
767where
768 T: FromIterator<U>,
769 U: FromStr,
770 U::Err: Into<Box<dyn error::Error + Sync + Send>>,
771{
772 fn decode<I>(_: &ConjureRuntime, params: I) -> Result<T, Error>
773 where
774 I: IntoIterator,
775 I::Item: AsRef<str>,
776 {
777 params
778 .into_iter()
779 .map(|s| {
780 s.as_ref()
781 .parse()
782 .map_err(|e| Error::service(e, InvalidArgument::new()))
783 })
784 .collect()
785 }
786}
787
788fn only_item<I>(it: I) -> Result<I::Item, Error>
789where
790 I: IntoIterator,
791{
792 let mut it = it.into_iter();
793 let Some(item) = it.next() else {
794 return Err(
795 Error::service_safe("expected exactly 1 parameter", InvalidArgument::new())
796 .with_safe_param("actual", 0),
797 );
798 };
799
800 let remaining = it.count();
801 if remaining > 0 {
802 return Err(
803 Error::service_safe("expected exactly 1 parameter", InvalidArgument::new())
804 .with_safe_param("actual", remaining + 1),
805 );
806 }
807
808 Ok(item)
809}
810
811pub struct FromDecoder<D, U> {
813 _p: PhantomData<(D, U)>,
814}
815
816impl<T, D, U> DecodeParam<T> for FromDecoder<D, U>
817where
818 T: From<U>,
819 D: DecodeParam<U>,
820{
821 fn decode<I>(runtime: &ConjureRuntime, params: I) -> Result<T, Error>
822 where
823 I: IntoIterator,
824 I::Item: AsRef<str>,
825 {
826 D::decode(runtime, params).map(T::from)
827 }
828}
829
830impl<T, D, U> DecodeHeader<T> for FromDecoder<D, U>
831where
832 T: From<U>,
833 D: DecodeHeader<U>,
834{
835 fn decode<'a, I>(runtime: &ConjureRuntime, headers: I) -> Result<T, Error>
836 where
837 I: IntoIterator<Item = &'a HeaderValue>,
838 {
839 D::decode(runtime, headers).map(T::from)
840 }
841}