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::ops::Deref;
32use std::pin::Pin;
33use std::str;
34use std::str::FromStr;
35use std::sync::Arc;
36
37use crate::private::{self, SERIALIZABLE_REQUEST_SIZE_LIMIT};
38pub use crate::server::encoding::*;
39#[doc(inline)]
40pub use crate::server::runtime::ConjureRuntime;
41
42pub mod conjure;
43mod encoding;
44pub mod runtime;
45
46pub trait EndpointMetadata {
48 fn method(&self) -> Method;
50
51 fn path(&self) -> &[PathSegment];
55
56 fn template(&self) -> &str;
60
61 fn service_name(&self) -> &str;
63
64 fn name(&self) -> &str;
66
67 fn deprecated(&self) -> Option<&str>;
69}
70
71impl<T> EndpointMetadata for Box<T>
72where
73 T: ?Sized + EndpointMetadata,
74{
75 fn method(&self) -> Method {
76 (**self).method()
77 }
78
79 fn path(&self) -> &[PathSegment] {
80 (**self).path()
81 }
82
83 fn template(&self) -> &str {
84 (**self).template()
85 }
86
87 fn service_name(&self) -> &str {
88 (**self).service_name()
89 }
90
91 fn name(&self) -> &str {
92 (**self).name()
93 }
94
95 fn deprecated(&self) -> Option<&str> {
96 (**self).deprecated()
97 }
98}
99
100pub trait Endpoint<I, O>: EndpointMetadata {
102 fn handle(
112 &self,
113 req: Request<I>,
114 response_extensions: &mut Extensions,
115 ) -> Result<Response<ResponseBody<O>>, Error>;
116}
117
118impl<T, I, O> Endpoint<I, O> for Box<T>
119where
120 T: ?Sized + Endpoint<I, O>,
121{
122 fn handle(
123 &self,
124 req: Request<I>,
125 response_extensions: &mut Extensions,
126 ) -> Result<Response<ResponseBody<O>>, Error> {
127 (**self).handle(req, response_extensions)
128 }
129}
130
131pub trait AsyncEndpoint<I, O>: EndpointMetadata {
133 fn handle(
143 &self,
144 req: Request<I>,
145 response_extensions: &mut Extensions,
146 ) -> impl Future<Output = Result<Response<AsyncResponseBody<O>>, Error>> + Send;
147}
148
149impl<T, I, O> AsyncEndpoint<I, O> for Box<T>
150where
151 T: ?Sized + AsyncEndpoint<I, O>,
152{
153 fn handle(
154 &self,
155 req: Request<I>,
156 response_extensions: &mut Extensions,
157 ) -> impl Future<Output = Result<Response<AsyncResponseBody<O>>, Error>> + Send {
158 (**self).handle(req, response_extensions)
159 }
160}
161
162trait AsyncEndpointEraser<I, O>: EndpointMetadata {
164 #[allow(clippy::type_complexity)]
165 fn handle<'a>(
166 &'a self,
167 req: Request<I>,
168 response_extensions: &'a mut Extensions,
169 ) -> Pin<Box<dyn Future<Output = Result<Response<AsyncResponseBody<O>>, Error>> + Send + 'a>>
170 where
171 I: 'a,
172 O: 'a;
173}
174
175impl<T, I, O> AsyncEndpointEraser<I, O> for T
176where
177 T: AsyncEndpoint<I, O>,
178{
179 fn handle<'a>(
180 &'a self,
181 req: Request<I>,
182 response_extensions: &'a mut Extensions,
183 ) -> Pin<Box<dyn Future<Output = Result<Response<AsyncResponseBody<O>>, Error>> + Send + 'a>>
184 where
185 I: 'a,
186 O: 'a,
187 {
188 Box::pin(self.handle(req, response_extensions))
189 }
190}
191
192pub struct BoxAsyncEndpoint<'a, I, O> {
194 inner: Box<dyn AsyncEndpointEraser<I, O> + 'a + Sync + Send>,
195}
196
197impl<'a, I, O> BoxAsyncEndpoint<'a, I, O> {
198 pub fn new<T>(v: T) -> Self
200 where
201 T: AsyncEndpoint<I, O> + Sync + Send + 'a,
202 {
203 BoxAsyncEndpoint { inner: Box::new(v) }
204 }
205}
206
207impl<I, O> EndpointMetadata for BoxAsyncEndpoint<'_, I, O> {
208 fn method(&self) -> Method {
209 self.inner.method()
210 }
211
212 fn path(&self) -> &[PathSegment] {
213 self.inner.path()
214 }
215
216 fn template(&self) -> &str {
217 self.inner.template()
218 }
219
220 fn service_name(&self) -> &str {
221 self.inner.service_name()
222 }
223
224 fn name(&self) -> &str {
225 self.inner.name()
226 }
227
228 fn deprecated(&self) -> Option<&str> {
229 self.inner.deprecated()
230 }
231}
232
233impl<I, O> AsyncEndpoint<I, O> for BoxAsyncEndpoint<'_, I, O>
234where
235 I: Send,
236{
237 async fn handle(
238 &self,
239 req: Request<I>,
240 response_extensions: &mut Extensions,
241 ) -> Result<Response<AsyncResponseBody<O>>, Error> {
242 self.inner.handle(req, response_extensions).await
243 }
244}
245
246#[derive(Debug, Clone)]
248pub enum PathSegment {
249 Literal(Cow<'static, str>),
251
252 Parameter {
254 name: Cow<'static, str>,
256
257 regex: Option<Cow<'static, str>>,
259 },
260}
261
262pub enum ResponseBody<O> {
264 Empty,
266 Fixed(Bytes),
268 Streaming(Box<dyn WriteBody<O>>),
270}
271
272pub enum AsyncResponseBody<O> {
274 Empty,
276 Fixed(Bytes),
278 Streaming(BoxAsyncWriteBody<'static, O>),
280}
281
282pub trait Service<I, O> {
284 fn endpoints(
286 &self,
287 runtime: &Arc<ConjureRuntime>,
288 ) -> Vec<Box<dyn Endpoint<I, O> + Sync + Send>>;
289}
290
291pub trait AsyncService<I, O> {
293 fn endpoints(&self, runtime: &Arc<ConjureRuntime>) -> Vec<BoxAsyncEndpoint<'static, I, O>>;
295}
296
297pub trait WriteBody<W> {
299 fn write_body(self: Box<Self>, w: &mut W) -> Result<(), Error>;
302}
303
304impl<W> WriteBody<W> for Vec<u8>
305where
306 W: Write,
307{
308 fn write_body(self: Box<Self>, w: &mut W) -> Result<(), Error> {
309 w.write_all(&self).map_err(Error::internal_safe)
310 }
311}
312
313pub trait AsyncWriteBody<W> {
335 fn write_body(self, w: Pin<&mut W>) -> impl Future<Output = Result<(), Error>> + Send;
337}
338
339trait AsyncWriteBodyEraser<W> {
341 fn write_body<'a>(
342 self: Box<Self>,
343 w: Pin<&'a mut W>,
344 ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'a>>
345 where
346 Self: 'a;
347}
348
349impl<T, W> AsyncWriteBodyEraser<W> for T
350where
351 T: AsyncWriteBody<W>,
352{
353 fn write_body<'a>(
354 self: Box<Self>,
355 w: Pin<&'a mut W>,
356 ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'a>>
357 where
358 Self: 'a,
359 {
360 Box::pin((*self).write_body(w))
361 }
362}
363
364pub struct BoxAsyncWriteBody<'a, W> {
366 inner: Box<dyn AsyncWriteBodyEraser<W> + Send + 'a>,
367}
368
369impl<'a, W> BoxAsyncWriteBody<'a, W> {
370 pub fn new<T>(v: T) -> Self
372 where
373 T: AsyncWriteBody<W> + Send + 'a,
374 {
375 BoxAsyncWriteBody { inner: Box::new(v) }
376 }
377}
378
379impl<W> AsyncWriteBody<W> for BoxAsyncWriteBody<'_, W>
380where
381 W: Send,
382{
383 async fn write_body(self, w: Pin<&mut W>) -> Result<(), Error>
384 where
385 W: Send,
386 {
387 self.inner.write_body(w).await
388 }
389}
390
391pub struct RequestContext<'a> {
396 request_parts: MaybeBorrowed<'a, request::Parts>,
397 response_extensions: &'a mut Extensions,
398}
399
400impl<'a> RequestContext<'a> {
401 #[doc(hidden)]
403 #[inline]
404 pub fn new(request_parts: request::Parts, response_extensions: &'a mut Extensions) -> Self {
406 RequestContext {
407 request_parts: MaybeBorrowed::Owned(request_parts),
408 response_extensions,
409 }
410 }
411
412 #[doc(hidden)]
413 #[inline]
414 pub fn new2(
415 request_parts: &'a request::Parts,
416 response_extensions: &'a mut Extensions,
417 ) -> Self {
418 RequestContext {
419 request_parts: MaybeBorrowed::Borrowed(request_parts),
420 response_extensions,
421 }
422 }
423
424 #[inline]
426 pub fn request_uri(&self) -> &Uri {
427 &self.request_parts.uri
428 }
429
430 #[inline]
432 pub fn request_headers(&self) -> &HeaderMap {
433 &self.request_parts.headers
434 }
435
436 #[inline]
438 pub fn request_extensions(&self) -> &Extensions {
439 &self.request_parts.extensions
440 }
441
442 #[inline]
444 pub fn response_extensions(&self) -> &Extensions {
445 self.response_extensions
446 }
447
448 #[inline]
450 pub fn response_extensions_mut(&mut self) -> &mut Extensions {
451 self.response_extensions
452 }
453}
454
455enum MaybeBorrowed<'a, T> {
456 Borrowed(&'a T),
457 Owned(T),
458}
459
460impl<T> Deref for MaybeBorrowed<'_, T> {
461 type Target = T;
462
463 #[inline]
464 fn deref(&self) -> &Self::Target {
465 match self {
466 MaybeBorrowed::Borrowed(v) => v,
467 MaybeBorrowed::Owned(v) => v,
468 }
469 }
470}
471
472pub trait DeserializeRequest<T, R> {
475 fn deserialize(runtime: &ConjureRuntime, headers: &HeaderMap, body: R) -> Result<T, Error>;
477}
478
479pub trait AsyncDeserializeRequest<T, R> {
482 fn deserialize(
484 runtime: &ConjureRuntime,
485 headers: &HeaderMap,
486 body: R,
487 ) -> impl Future<Output = Result<T, Error>> + Send;
488}
489
490pub enum StdRequestDeserializer<const N: usize = { SERIALIZABLE_REQUEST_SIZE_LIMIT }> {}
495
496impl<const N: usize, T, R> DeserializeRequest<T, R> for StdRequestDeserializer<N>
497where
498 T: DeserializeOwned,
499 R: Iterator<Item = Result<Bytes, Error>>,
500{
501 fn deserialize(runtime: &ConjureRuntime, headers: &HeaderMap, body: R) -> Result<T, Error> {
502 let encoding = runtime.request_body_encoding(headers)?;
503 let buf = private::read_body(body, Some(N))?;
504 let v = T::deserialize(encoding.deserializer(&buf).deserializer())
505 .map_err(|e| Error::service(e, InvalidArgument::new()))?;
506 Ok(v)
507 }
508}
509
510impl<const N: usize, T, R> AsyncDeserializeRequest<T, R> for StdRequestDeserializer<N>
511where
512 T: DeserializeOwned,
513 R: Stream<Item = Result<Bytes, Error>> + Send,
514{
515 async fn deserialize(
516 runtime: &ConjureRuntime,
517 headers: &HeaderMap,
518 body: R,
519 ) -> Result<T, Error> {
520 let encoding = runtime.request_body_encoding(headers)?;
521 let buf = private::async_read_body(body, Some(N)).await?;
522 let v = T::deserialize(encoding.deserializer(&buf).deserializer())
523 .map_err(|e| Error::service(e, InvalidArgument::new()))?;
524 Ok(v)
525 }
526}
527
528pub struct FromRequestDeserializer<D, U> {
530 _p: PhantomData<(D, U)>,
531}
532
533impl<T, R, D, U> DeserializeRequest<T, R> for FromRequestDeserializer<D, U>
534where
535 T: From<U>,
536 D: DeserializeRequest<U, R>,
537{
538 fn deserialize(runtime: &ConjureRuntime, headers: &HeaderMap, body: R) -> Result<T, Error> {
539 D::deserialize(runtime, headers, body).map(From::from)
540 }
541}
542
543impl<T, R, D, U> AsyncDeserializeRequest<T, R> for FromRequestDeserializer<D, U>
544where
545 T: From<U>,
546 D: AsyncDeserializeRequest<U, R>,
547 R: Send,
548{
549 async fn deserialize(
550 runtime: &ConjureRuntime,
551 headers: &HeaderMap,
552 body: R,
553 ) -> Result<T, Error> {
554 D::deserialize(runtime, headers, body).await.map(From::from)
555 }
556}
557
558pub trait SerializeResponse<T, W> {
560 fn serialize(
562 runtime: &ConjureRuntime,
563 request_headers: &HeaderMap,
564 value: T,
565 ) -> Result<Response<ResponseBody<W>>, Error>;
566}
567
568pub trait AsyncSerializeResponse<T, W> {
571 fn serialize(
573 runtime: &ConjureRuntime,
574 request_headers: &HeaderMap,
575 value: T,
576 ) -> Result<Response<AsyncResponseBody<W>>, Error>;
577}
578
579pub enum EmptyResponseSerializer {}
581
582impl EmptyResponseSerializer {
583 fn serialize_inner<T>(body: T) -> Result<Response<T>, Error> {
584 let mut response = Response::new(body);
585 *response.status_mut() = StatusCode::NO_CONTENT;
586 Ok(response)
587 }
588}
589
590impl<W> SerializeResponse<(), W> for EmptyResponseSerializer {
591 fn serialize(
592 _: &ConjureRuntime,
593 _: &HeaderMap,
594 _: (),
595 ) -> Result<Response<ResponseBody<W>>, Error> {
596 Self::serialize_inner(ResponseBody::Empty)
597 }
598}
599
600impl<W> AsyncSerializeResponse<(), W> for EmptyResponseSerializer {
601 fn serialize(
602 _: &ConjureRuntime,
603 _: &HeaderMap,
604 _: (),
605 ) -> Result<Response<AsyncResponseBody<W>>, Error> {
606 Self::serialize_inner(AsyncResponseBody::Empty)
607 }
608}
609
610pub enum StdResponseSerializer {}
612
613impl StdResponseSerializer {
614 fn serialize_inner<B>(
615 runtime: &ConjureRuntime,
616 request_headers: &HeaderMap,
617 value: &dyn erased_serde::Serialize,
618 make_body: impl FnOnce(Bytes) -> B,
619 ) -> Result<Response<B>, Error> {
620 let encoding = runtime.response_body_encoding(request_headers)?;
621
622 let mut body = vec![];
623 value
624 .erased_serialize(&mut *encoding.serializer(&mut body).serializer())
625 .map_err(Error::internal)?;
626
627 let mut response = Response::new(make_body(body.into()));
628 response
629 .headers_mut()
630 .insert(CONTENT_TYPE, encoding.content_type());
631
632 Ok(response)
633 }
634}
635
636impl<T, W> SerializeResponse<T, W> for StdResponseSerializer
637where
638 T: Serialize,
639{
640 fn serialize(
641 runtime: &ConjureRuntime,
642 request_headers: &HeaderMap,
643 value: T,
644 ) -> Result<Response<ResponseBody<W>>, Error> {
645 Self::serialize_inner(runtime, request_headers, &value, ResponseBody::Fixed)
646 }
647}
648
649impl<T, W> AsyncSerializeResponse<T, W> for StdResponseSerializer
650where
651 T: Serialize,
652{
653 fn serialize(
654 runtime: &ConjureRuntime,
655 request_headers: &HeaderMap,
656 value: T,
657 ) -> Result<Response<AsyncResponseBody<W>>, Error> {
658 Self::serialize_inner(runtime, request_headers, &value, AsyncResponseBody::Fixed)
659 }
660}
661
662pub trait DecodeHeader<T> {
664 fn decode<'a, I>(runtime: &ConjureRuntime, headers: I) -> Result<T, Error>
666 where
667 I: IntoIterator<Item = &'a HeaderValue>;
668}
669
670pub trait DecodeParam<T> {
673 fn decode<I>(runtime: &ConjureRuntime, params: I) -> Result<T, Error>
677 where
678 I: IntoIterator,
679 I::Item: AsRef<str>;
680}
681
682pub enum FromStrDecoder {}
684
685impl<T> DecodeHeader<T> for FromStrDecoder
686where
687 T: FromStr,
688 T::Err: Into<Box<dyn error::Error + Sync + Send>>,
689{
690 fn decode<'a, I>(_: &ConjureRuntime, headers: I) -> Result<T, Error>
691 where
692 I: IntoIterator<Item = &'a HeaderValue>,
693 {
694 only_item(headers)?
695 .to_str()
696 .map_err(|e| Error::service(e, InvalidArgument::new()))?
697 .parse()
698 .map_err(|e| Error::service(e, InvalidArgument::new()))
699 }
700}
701
702impl<T> DecodeParam<T> for FromStrDecoder
703where
704 T: FromStr,
705 T::Err: Into<Box<dyn error::Error + Sync + Send>>,
706{
707 fn decode<I>(_: &ConjureRuntime, params: I) -> Result<T, Error>
708 where
709 I: IntoIterator,
710 I::Item: AsRef<str>,
711 {
712 only_item(params)?
713 .as_ref()
714 .parse()
715 .map_err(|e| Error::service(e, InvalidArgument::new()))
716 }
717}
718
719pub enum FromStrOptionDecoder {}
721
722impl<T> DecodeHeader<Option<T>> for FromStrOptionDecoder
723where
724 T: FromStr,
725 T::Err: Into<Box<dyn error::Error + Sync + Send>>,
726{
727 fn decode<'a, I>(_: &ConjureRuntime, headers: I) -> Result<Option<T>, Error>
728 where
729 I: IntoIterator<Item = &'a HeaderValue>,
730 {
731 let Some(header) = optional_item(headers)? else {
732 return Ok(None);
733 };
734 let value = header
735 .to_str()
736 .map_err(|e| Error::service(e, InvalidArgument::new()))?
737 .parse()
738 .map_err(|e| Error::service(e, InvalidArgument::new()))?;
739 Ok(Some(value))
740 }
741}
742
743impl<T> DecodeParam<Option<T>> for FromStrOptionDecoder
744where
745 T: FromStr,
746 T::Err: Into<Box<dyn error::Error + Sync + Send>>,
747{
748 fn decode<I>(_: &ConjureRuntime, params: I) -> Result<Option<T>, Error>
749 where
750 I: IntoIterator,
751 I::Item: AsRef<str>,
752 {
753 let Some(param) = optional_item(params)? else {
754 return Ok(None);
755 };
756 let value = param
757 .as_ref()
758 .parse()
759 .map_err(|e| Error::service(e, InvalidArgument::new()))?;
760 Ok(Some(value))
761 }
762}
763
764fn optional_item<I>(it: I) -> Result<Option<I::Item>, Error>
765where
766 I: IntoIterator,
767{
768 let mut it = it.into_iter();
769 let Some(item) = it.next() else {
770 return Ok(None);
771 };
772
773 let remaining = it.count();
774 if remaining > 0 {
775 return Err(
776 Error::service_safe("expected at most 1 parameter", InvalidArgument::new())
777 .with_safe_param("actual", remaining + 1),
778 );
779 }
780
781 Ok(Some(item))
782}
783
784pub struct FromStrSeqDecoder<U> {
787 _p: PhantomData<U>,
788}
789
790impl<T, U> DecodeParam<T> for FromStrSeqDecoder<U>
791where
792 T: FromIterator<U>,
793 U: FromStr,
794 U::Err: Into<Box<dyn error::Error + Sync + Send>>,
795{
796 fn decode<I>(_: &ConjureRuntime, params: I) -> Result<T, Error>
797 where
798 I: IntoIterator,
799 I::Item: AsRef<str>,
800 {
801 params
802 .into_iter()
803 .map(|s| {
804 s.as_ref()
805 .parse()
806 .map_err(|e| Error::service(e, InvalidArgument::new()))
807 })
808 .collect()
809 }
810}
811
812fn only_item<I>(it: I) -> Result<I::Item, Error>
813where
814 I: IntoIterator,
815{
816 let mut it = it.into_iter();
817 let Some(item) = it.next() else {
818 return Err(
819 Error::service_safe("expected exactly 1 parameter", InvalidArgument::new())
820 .with_safe_param("actual", 0),
821 );
822 };
823
824 let remaining = it.count();
825 if remaining > 0 {
826 return Err(
827 Error::service_safe("expected exactly 1 parameter", InvalidArgument::new())
828 .with_safe_param("actual", remaining + 1),
829 );
830 }
831
832 Ok(item)
833}
834
835pub struct FromDecoder<D, U> {
837 _p: PhantomData<(D, U)>,
838}
839
840impl<T, D, U> DecodeParam<T> for FromDecoder<D, U>
841where
842 T: From<U>,
843 D: DecodeParam<U>,
844{
845 fn decode<I>(runtime: &ConjureRuntime, params: I) -> Result<T, Error>
846 where
847 I: IntoIterator,
848 I::Item: AsRef<str>,
849 {
850 D::decode(runtime, params).map(T::from)
851 }
852}
853
854impl<T, D, U> DecodeHeader<T> for FromDecoder<D, U>
855where
856 T: From<U>,
857 D: DecodeHeader<U>,
858{
859 fn decode<'a, I>(runtime: &ConjureRuntime, headers: I) -> Result<T, Error>
860 where
861 I: IntoIterator<Item = &'a HeaderValue>,
862 {
863 D::decode(runtime, headers).map(T::from)
864 }
865}