conjure_http/server/
mod.rs

1// Copyright 2019 Palantir Technologies, Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! The Conjure HTTP server API.
16use 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
45/// Metadata about an HTTP endpoint.
46pub trait EndpointMetadata {
47    /// The endpoint's HTTP method.
48    fn method(&self) -> Method;
49
50    /// The endpoint's parsed HTTP URI path.
51    ///
52    /// Each value in the slice represents one segment of the URI.
53    fn path(&self) -> &[PathSegment];
54
55    /// The endpoint's raw HTTP URI template.
56    ///
57    /// Use the [`Self::path()`] method for routing rather than parsing this string.
58    fn template(&self) -> &str;
59
60    /// The name of the service defining this endpoint.
61    fn service_name(&self) -> &str;
62
63    /// The name of the endpoint.
64    fn name(&self) -> &str;
65
66    /// If the endpoint is deprecated, returns the deprecation documentation.
67    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
99/// A blocking HTTP endpoint.
100pub trait Endpoint<I, O>: EndpointMetadata {
101    /// Handles a request to the endpoint.
102    ///
103    /// If the endpoint has path parameters, callers must include a
104    /// [`PathParams`](crate::PathParams) extension in the request containing the extracted
105    /// parameters from the URI. The implementation is reponsible for all other request handling,
106    /// including parsing query parameters, header parameters, and the request body.
107    ///
108    /// The `response_extensions` will be added to the extensions of the response produced by the
109    /// endpoint, even if an error is returned.
110    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
130/// A nonblocking HTTP endpoint.
131pub trait AsyncEndpoint<I, O>: EndpointMetadata {
132    /// Handles a request to the endpoint.
133    ///
134    /// If the endpoint has path parameters, callers must include a
135    /// [`PathParams`](crate::PathParams) extension in the request containing the extracted
136    /// parameters from the URI. The implementation is reponsible for all other request handling,
137    /// including parsing query parameters, header parameters, and the request body.
138    ///
139    /// The `response_extensions` will be added to the extensions of the response produced by the
140    /// endpoint, even if an error is returned.
141    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
161// An internal object-safe version of AsyncEndpoint used to implement BoxAsyncEndpoint
162trait 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
191/// A boxed [`AsyncEndpoint`] trait object.
192pub 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    /// Creates a new `BoxAsyncEndpoint`.
198    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/// A nonblocking local HTTP endpoint.
246pub trait LocalAsyncEndpoint<I, O>: EndpointMetadata {
247    /// Handles a request to the endpoint.
248    ///
249    /// If the endpoint has path parameters, callers must include a
250    /// [`PathParams`](crate::PathParams) extension in the request containing the extracted
251    /// parameters from the URI. The implementation is reponsible for all other request handling,
252    /// including parsing query parameters, header parameters, and the request body.
253    ///
254    /// The `response_extensions` will be added to the extensions of the response produced by the
255    /// endpoint, even if an error is returned.
256    fn handle(
257        &self,
258        req: Request<I>,
259        response_extensions: &mut Extensions,
260    ) -> impl Future<Output = Result<Response<LocalAsyncResponseBody<O>>, Error>>;
261}
262
263impl<T, I, O> LocalAsyncEndpoint<I, O> for Box<T>
264where
265    T: ?Sized + LocalAsyncEndpoint<I, O>,
266{
267    fn handle(
268        &self,
269        req: Request<I>,
270        response_extensions: &mut Extensions,
271    ) -> impl Future<Output = Result<Response<LocalAsyncResponseBody<O>>, Error>> {
272        (**self).handle(req, response_extensions)
273    }
274}
275
276// An internal object-safe version of LocalAsyncEndpoint used to implement BoxLocalAsyncEndpoint
277trait LocalAsyncEndpointEraser<I, O>: EndpointMetadata {
278    #[allow(clippy::type_complexity)]
279    fn handle<'a>(
280        &'a self,
281        req: Request<I>,
282        response_extensions: &'a mut Extensions,
283    ) -> Pin<Box<dyn Future<Output = Result<Response<LocalAsyncResponseBody<O>>, Error>> + 'a>>
284    where
285        I: 'a,
286        O: 'a;
287}
288
289impl<T, I, O> LocalAsyncEndpointEraser<I, O> for T
290where
291    T: LocalAsyncEndpoint<I, O>,
292{
293    fn handle<'a>(
294        &'a self,
295        req: Request<I>,
296        response_extensions: &'a mut Extensions,
297    ) -> Pin<Box<dyn Future<Output = Result<Response<LocalAsyncResponseBody<O>>, Error>> + 'a>>
298    where
299        I: 'a,
300        O: 'a,
301    {
302        Box::pin(self.handle(req, response_extensions))
303    }
304}
305
306/// A boxed [`LocalAsyncEndpoint`] trait object.
307pub struct BoxLocalAsyncEndpoint<'a, I, O> {
308    inner: Box<dyn LocalAsyncEndpointEraser<I, O> + 'a>,
309}
310
311impl<'a, I, O> BoxLocalAsyncEndpoint<'a, I, O> {
312    /// Creates a new `BoxLocalAsyncEndpoint`.
313    pub fn new<T>(v: T) -> Self
314    where
315        T: LocalAsyncEndpoint<I, O> + 'a,
316    {
317        BoxLocalAsyncEndpoint { inner: Box::new(v) }
318    }
319}
320
321impl<I, O> EndpointMetadata for BoxLocalAsyncEndpoint<'_, I, O> {
322    fn method(&self) -> Method {
323        self.inner.method()
324    }
325
326    fn path(&self) -> &[PathSegment] {
327        self.inner.path()
328    }
329
330    fn template(&self) -> &str {
331        self.inner.template()
332    }
333
334    fn service_name(&self) -> &str {
335        self.inner.service_name()
336    }
337
338    fn name(&self) -> &str {
339        self.inner.name()
340    }
341
342    fn deprecated(&self) -> Option<&str> {
343        self.inner.deprecated()
344    }
345}
346
347impl<I, O> LocalAsyncEndpoint<I, O> for BoxLocalAsyncEndpoint<'_, I, O> {
348    async fn handle(
349        &self,
350        req: Request<I>,
351        response_extensions: &mut Extensions,
352    ) -> Result<Response<LocalAsyncResponseBody<O>>, Error> {
353        self.inner.handle(req, response_extensions).await
354    }
355}
356
357/// One segment of an endpoint URI template.
358#[derive(Debug, Clone)]
359pub enum PathSegment {
360    /// A literal string.
361    Literal(Cow<'static, str>),
362
363    /// A parameter.
364    Parameter {
365        /// The name of the parameter.
366        name: Cow<'static, str>,
367
368        /// The regex pattern used to match the pattern.
369        regex: Option<Cow<'static, str>>,
370    },
371}
372
373/// The response body returned from a blocking endpoint.
374pub enum ResponseBody<O> {
375    /// An empty body.
376    Empty,
377    /// A body buffered in memory.
378    Fixed(Bytes),
379    /// A streaming body.
380    Streaming(Box<dyn WriteBody<O>>),
381}
382
383/// The response body returned from an async endpoint.
384pub enum AsyncResponseBody<O> {
385    /// An empty body.
386    Empty,
387    /// A body buffered in memory.
388    Fixed(Bytes),
389    /// A streaming body.
390    Streaming(BoxAsyncWriteBody<'static, O>),
391}
392
393/// The response body returned from a local async endpoint.
394pub enum LocalAsyncResponseBody<O> {
395    /// An empty body.
396    Empty,
397    /// A body buffered in memory.
398    Fixed(Bytes),
399    /// A streaming body.
400    Streaming(BoxLocalAsyncWriteBody<'static, O>),
401}
402
403/// A blocking Conjure service.
404pub trait Service<I, O> {
405    /// Returns the endpoints in the service.
406    fn endpoints(
407        &self,
408        runtime: &Arc<ConjureRuntime>,
409    ) -> Vec<Box<dyn Endpoint<I, O> + Sync + Send>>;
410}
411
412/// An async Conjure service.
413pub trait AsyncService<I, O> {
414    /// Returns the endpoints in the service.
415    fn endpoints(&self, runtime: &Arc<ConjureRuntime>) -> Vec<BoxAsyncEndpoint<'static, I, O>>;
416}
417
418/// A local async Conjure service.
419pub trait LocalAsyncService<I, O> {
420    /// Returns the endpoints in the service.
421    fn endpoints(&self, runtime: &Arc<ConjureRuntime>)
422        -> Vec<BoxLocalAsyncEndpoint<'static, I, O>>;
423}
424
425/// A trait implemented by streaming bodies.
426pub trait WriteBody<W> {
427    /// Writes the body out, in its entirety.
428    // This should not be limited to `Box<Self>`, but it otherwise can't be used as a trait object currently :(
429    fn write_body(self: Box<Self>, w: &mut W) -> Result<(), Error>;
430}
431
432impl<W> WriteBody<W> for Vec<u8>
433where
434    W: Write,
435{
436    fn write_body(self: Box<Self>, w: &mut W) -> Result<(), Error> {
437        w.write_all(&self).map_err(Error::internal_safe)
438    }
439}
440
441/// A trait implemented by asynchronous streaming bodies.
442///
443/// # Examples
444///
445/// ```ignore
446/// use conjure_error::Error;
447/// use conjure_http::server::AsyncWriteBody;
448/// use std::pin::Pin;
449/// use tokio_io::{AsyncWrite, AsyncWriteExt};
450///
451/// pub struct SimpleBodyWriter;
452///
453/// impl<W> AsyncWriteBody<W> for SimpleBodyWriter
454/// where
455///     W: AsyncWrite + Send,
456/// {
457///     async fn write_body(self, mut w: Pin<&mut W>) -> Result<(), Error> {
458///         w.write_all(b"hello world").await.map_err(Error::internal_safe)
459///     }
460/// }
461/// ```
462pub trait AsyncWriteBody<W> {
463    /// Writes the body out, in its entirety.
464    fn write_body(self, w: Pin<&mut W>) -> impl Future<Output = Result<(), Error>> + Send;
465}
466
467// An internal object-safe version of AsyncWriteBody used to implement BoxAsyncWriteBody
468trait AsyncWriteBodyEraser<W> {
469    fn write_body<'a>(
470        self: Box<Self>,
471        w: Pin<&'a mut W>,
472    ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'a>>
473    where
474        Self: 'a;
475}
476
477impl<T, W> AsyncWriteBodyEraser<W> for T
478where
479    T: AsyncWriteBody<W>,
480{
481    fn write_body<'a>(
482        self: Box<Self>,
483        w: Pin<&'a mut W>,
484    ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'a>>
485    where
486        Self: 'a,
487    {
488        Box::pin((*self).write_body(w))
489    }
490}
491
492/// A boxed [`AsyncWriteBody`] trait object.
493pub struct BoxAsyncWriteBody<'a, W> {
494    inner: Box<dyn AsyncWriteBodyEraser<W> + Send + 'a>,
495}
496
497impl<'a, W> BoxAsyncWriteBody<'a, W> {
498    /// Creates a new `BoxAsyncWriteBody`.
499    pub fn new<T>(v: T) -> Self
500    where
501        T: AsyncWriteBody<W> + Send + 'a,
502    {
503        BoxAsyncWriteBody { inner: Box::new(v) }
504    }
505}
506
507impl<W> AsyncWriteBody<W> for BoxAsyncWriteBody<'_, W>
508where
509    W: Send,
510{
511    async fn write_body(self, w: Pin<&mut W>) -> Result<(), Error>
512    where
513        W: Send,
514    {
515        self.inner.write_body(w).await
516    }
517}
518
519/// A trait implemented by local asynchronous streaming bodies.
520///
521/// # Examples
522///
523/// ```ignore
524/// use conjure_error::Error;
525/// use conjure_http::server::LocalAsyncWriteBody;
526/// use std::pin::Pin;
527/// use tokio_io::{AsyncWrite, AsyncWriteExt};
528///
529/// pub struct SimpleBodyWriter;
530///
531/// impl<W> LocalAsyncWriteBody<W> for SimpleBodyWriter
532/// where
533///     W: AsyncWrite,
534/// {
535///     async fn write_body(self, mut w: Pin<&mut W>) -> Result<(), Error> {
536///         w.write_all(b"hello world").await.map_err(Error::internal_safe)
537///     }
538/// }
539/// ```
540pub trait LocalAsyncWriteBody<W> {
541    /// Writes the body out, in its entirety.
542    fn write_body(self, w: Pin<&mut W>) -> impl Future<Output = Result<(), Error>>;
543}
544
545// An internal object-safe version of LocalAsyncWriteBody used to implement BoxLocalAsyncWriteBody
546trait LocalAsyncWriteBodyEraser<W> {
547    fn write_body<'a>(
548        self: Box<Self>,
549        w: Pin<&'a mut W>,
550    ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + 'a>>
551    where
552        Self: 'a;
553}
554
555impl<T, W> LocalAsyncWriteBodyEraser<W> for T
556where
557    T: LocalAsyncWriteBody<W>,
558{
559    fn write_body<'a>(
560        self: Box<Self>,
561        w: Pin<&'a mut W>,
562    ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + 'a>>
563    where
564        Self: 'a,
565    {
566        Box::pin((*self).write_body(w))
567    }
568}
569
570/// A boxed [`LocalAsyncWriteBody`] trait object.
571pub struct BoxLocalAsyncWriteBody<'a, W> {
572    inner: Box<dyn LocalAsyncWriteBodyEraser<W> + 'a>,
573}
574
575impl<'a, W> BoxLocalAsyncWriteBody<'a, W> {
576    /// Creates a new `BoxLocalAsyncWriteBody`.
577    pub fn new<T>(v: T) -> Self
578    where
579        T: LocalAsyncWriteBody<W> + 'a,
580    {
581        BoxLocalAsyncWriteBody { inner: Box::new(v) }
582    }
583}
584
585impl<W> LocalAsyncWriteBody<W> for BoxLocalAsyncWriteBody<'_, W> {
586    async fn write_body(self, w: Pin<&mut W>) -> Result<(), Error> {
587        self.inner.write_body(w).await
588    }
589}
590
591/// An object containing extra low-level contextual information about a request.
592///
593/// Conjure service endpoints declared with the `server-request-context` tag will be passed a
594/// `RequestContext` in the generated trait.
595pub struct RequestContext<'a> {
596    request_parts: &'a request::Parts,
597    response_extensions: &'a mut Extensions,
598}
599
600impl<'a> RequestContext<'a> {
601    #[doc(hidden)]
602    #[inline]
603    pub fn new(request_parts: &'a request::Parts, response_extensions: &'a mut Extensions) -> Self {
604        RequestContext {
605            request_parts,
606            response_extensions,
607        }
608    }
609
610    /// Returns the request's URI.
611    #[inline]
612    pub fn request_uri(&self) -> &Uri {
613        &self.request_parts.uri
614    }
615
616    /// Returns a shared reference to the request's headers.
617    #[inline]
618    pub fn request_headers(&self) -> &HeaderMap {
619        &self.request_parts.headers
620    }
621
622    /// Returns a shared reference to the request's extensions.
623    #[inline]
624    pub fn request_extensions(&self) -> &Extensions {
625        &self.request_parts.extensions
626    }
627
628    /// Returns a shared reference to extensions that will be added to the response.
629    #[inline]
630    pub fn response_extensions(&self) -> &Extensions {
631        self.response_extensions
632    }
633
634    /// Returns a mutable reference to extensions that will be added to the response.
635    #[inline]
636    pub fn response_extensions_mut(&mut self) -> &mut Extensions {
637        self.response_extensions
638    }
639}
640
641/// A marker value to opt into legacy error serialization.
642///
643/// If present in the response extensions of a request, server implementations should use
644/// [`conjure_error::stringify_parameters`] to convert all error parameters to their legacy
645/// stringified format.
646#[derive(Copy, Clone, Debug)]
647pub struct UseLegacyErrorSerialization;
648
649/// A trait implemented by request body deserializers used by custom Conjure server trait
650/// implementations.
651pub trait DeserializeRequest<T, R> {
652    /// Deserializes the request body.
653    fn deserialize(runtime: &ConjureRuntime, headers: &HeaderMap, body: R) -> Result<T, Error>;
654}
655
656/// A trait implemented by response deserializers used by custom async Conjure server trait
657/// implementations.
658pub trait AsyncDeserializeRequest<T, R> {
659    /// Deserializes the request body.
660    fn deserialize(
661        runtime: &ConjureRuntime,
662        headers: &HeaderMap,
663        body: R,
664    ) -> impl Future<Output = Result<T, Error>> + Send;
665}
666
667/// A trait implemented by response deserializers used by custom local async Conjure server trait
668/// implementations.
669pub trait LocalAsyncDeserializeRequest<T, R> {
670    /// Deserializes the request body.
671    fn deserialize(
672        runtime: &ConjureRuntime,
673        headers: &HeaderMap,
674        body: R,
675    ) -> impl Future<Output = Result<T, Error>>;
676}
677
678/// A request deserializer for standard body types.
679///
680/// It is parameterized by the maximum number of bytes that will be read from the request body
681/// before an error is returned. The limit defaults to 50 MiB.
682pub enum StdRequestDeserializer<const N: usize = { SERIALIZABLE_REQUEST_SIZE_LIMIT }> {}
683
684impl<const N: usize> StdRequestDeserializer<N> {
685    async fn deserialize_inner<T, R>(
686        runtime: &ConjureRuntime,
687        headers: &HeaderMap,
688        body: R,
689    ) -> Result<T, Error>
690    where
691        T: DeserializeOwned,
692        R: Stream<Item = Result<Bytes, Error>>,
693    {
694        let encoding = runtime.request_body_encoding(headers)?;
695        let buf = private::async_read_body(body, Some(N)).await?;
696        let v = T::deserialize(encoding.deserializer(&buf).deserializer())
697            .map_err(|e| Error::service(e, InvalidArgument::new()))?;
698        Ok(v)
699    }
700}
701
702impl<const N: usize, T, R> DeserializeRequest<T, R> for StdRequestDeserializer<N>
703where
704    T: DeserializeOwned,
705    R: Iterator<Item = Result<Bytes, Error>>,
706{
707    fn deserialize(runtime: &ConjureRuntime, headers: &HeaderMap, body: R) -> Result<T, Error> {
708        let encoding = runtime.request_body_encoding(headers)?;
709        let buf = private::read_body(body, Some(N))?;
710        let v = T::deserialize(encoding.deserializer(&buf).deserializer())
711            .map_err(|e| Error::service(e, InvalidArgument::new()))?;
712        Ok(v)
713    }
714}
715
716impl<const N: usize, T, R> AsyncDeserializeRequest<T, R> for StdRequestDeserializer<N>
717where
718    T: DeserializeOwned,
719    R: Stream<Item = Result<Bytes, Error>> + Send,
720{
721    async fn deserialize(
722        runtime: &ConjureRuntime,
723        headers: &HeaderMap,
724        body: R,
725    ) -> Result<T, Error> {
726        Self::deserialize_inner(runtime, headers, body).await
727    }
728}
729
730impl<const N: usize, T, R> LocalAsyncDeserializeRequest<T, R> for StdRequestDeserializer<N>
731where
732    T: DeserializeOwned,
733    R: Stream<Item = Result<Bytes, Error>>,
734{
735    async fn deserialize(
736        runtime: &ConjureRuntime,
737        headers: &HeaderMap,
738        body: R,
739    ) -> Result<T, Error> {
740        Self::deserialize_inner(runtime, headers, body).await
741    }
742}
743
744/// A request deserializer which maps the output of another with [`From::from`].
745pub struct FromRequestDeserializer<D, U> {
746    _p: PhantomData<(D, U)>,
747}
748
749impl<T, R, D, U> DeserializeRequest<T, R> for FromRequestDeserializer<D, U>
750where
751    T: From<U>,
752    D: DeserializeRequest<U, R>,
753{
754    fn deserialize(runtime: &ConjureRuntime, headers: &HeaderMap, body: R) -> Result<T, Error> {
755        D::deserialize(runtime, headers, body).map(From::from)
756    }
757}
758
759impl<T, R, D, U> AsyncDeserializeRequest<T, R> for FromRequestDeserializer<D, U>
760where
761    T: From<U>,
762    D: AsyncDeserializeRequest<U, R>,
763    R: Send,
764{
765    async fn deserialize(
766        runtime: &ConjureRuntime,
767        headers: &HeaderMap,
768        body: R,
769    ) -> Result<T, Error> {
770        D::deserialize(runtime, headers, body).await.map(From::from)
771    }
772}
773
774impl<T, R, D, U> LocalAsyncDeserializeRequest<T, R> for FromRequestDeserializer<D, U>
775where
776    T: From<U>,
777    D: LocalAsyncDeserializeRequest<U, R>,
778{
779    async fn deserialize(
780        runtime: &ConjureRuntime,
781        headers: &HeaderMap,
782        body: R,
783    ) -> Result<T, Error> {
784        D::deserialize(runtime, headers, body).await.map(From::from)
785    }
786}
787
788/// A trait implemented by response serializers used by custom Conjure server trait implementations.
789pub trait SerializeResponse<T, W> {
790    /// Serializes the response.
791    fn serialize(
792        runtime: &ConjureRuntime,
793        request_headers: &HeaderMap,
794        value: T,
795    ) -> Result<Response<ResponseBody<W>>, Error>;
796}
797
798/// A trait implemented by response serializers used by custom async Conjure server trait
799/// implementations.
800pub trait AsyncSerializeResponse<T, W> {
801    /// Serializes the response.
802    fn serialize(
803        runtime: &ConjureRuntime,
804        request_headers: &HeaderMap,
805        value: T,
806    ) -> Result<Response<AsyncResponseBody<W>>, Error>;
807}
808
809/// A trait implemented by response serializers used by custom local async Conjure server trait
810/// implementations.
811pub trait LocalAsyncSerializeResponse<T, W> {
812    /// Serializes the response.
813    fn serialize(
814        runtime: &ConjureRuntime,
815        request_headers: &HeaderMap,
816        value: T,
817    ) -> Result<Response<LocalAsyncResponseBody<W>>, Error>;
818}
819
820/// A serializer which encodes `()` as an empty body and status code of `204 No Content`.
821pub enum EmptyResponseSerializer {}
822
823impl EmptyResponseSerializer {
824    fn serialize_inner<T>(body: T) -> Result<Response<T>, Error> {
825        let mut response = Response::new(body);
826        *response.status_mut() = StatusCode::NO_CONTENT;
827        Ok(response)
828    }
829}
830
831impl<W> SerializeResponse<(), W> for EmptyResponseSerializer {
832    fn serialize(
833        _: &ConjureRuntime,
834        _: &HeaderMap,
835        _: (),
836    ) -> Result<Response<ResponseBody<W>>, Error> {
837        Self::serialize_inner(ResponseBody::Empty)
838    }
839}
840
841impl<W> AsyncSerializeResponse<(), W> for EmptyResponseSerializer {
842    fn serialize(
843        _: &ConjureRuntime,
844        _: &HeaderMap,
845        _: (),
846    ) -> Result<Response<AsyncResponseBody<W>>, Error> {
847        Self::serialize_inner(AsyncResponseBody::Empty)
848    }
849}
850
851impl<W> LocalAsyncSerializeResponse<(), W> for EmptyResponseSerializer {
852    fn serialize(
853        _: &ConjureRuntime,
854        _: &HeaderMap,
855        _: (),
856    ) -> Result<Response<LocalAsyncResponseBody<W>>, Error> {
857        Self::serialize_inner(LocalAsyncResponseBody::Empty)
858    }
859}
860
861/// A body serializer for standard response types.
862pub enum StdResponseSerializer {}
863
864impl StdResponseSerializer {
865    fn serialize_inner<B>(
866        runtime: &ConjureRuntime,
867        request_headers: &HeaderMap,
868        value: &dyn erased_serde::Serialize,
869        make_body: impl FnOnce(Bytes) -> B,
870    ) -> Result<Response<B>, Error> {
871        let encoding = runtime.response_body_encoding(request_headers)?;
872
873        let mut body = vec![];
874        value
875            .erased_serialize(&mut *encoding.serializer(&mut body).serializer())
876            .map_err(Error::internal)?;
877
878        let mut response = Response::new(make_body(body.into()));
879        response
880            .headers_mut()
881            .insert(CONTENT_TYPE, encoding.content_type());
882
883        Ok(response)
884    }
885}
886
887impl<T, W> SerializeResponse<T, W> for StdResponseSerializer
888where
889    T: Serialize,
890{
891    fn serialize(
892        runtime: &ConjureRuntime,
893        request_headers: &HeaderMap,
894        value: T,
895    ) -> Result<Response<ResponseBody<W>>, Error> {
896        Self::serialize_inner(runtime, request_headers, &value, ResponseBody::Fixed)
897    }
898}
899
900impl<T, W> AsyncSerializeResponse<T, W> for StdResponseSerializer
901where
902    T: Serialize,
903{
904    fn serialize(
905        runtime: &ConjureRuntime,
906        request_headers: &HeaderMap,
907        value: T,
908    ) -> Result<Response<AsyncResponseBody<W>>, Error> {
909        Self::serialize_inner(runtime, request_headers, &value, AsyncResponseBody::Fixed)
910    }
911}
912
913impl<T, W> LocalAsyncSerializeResponse<T, W> for StdResponseSerializer
914where
915    T: Serialize,
916{
917    fn serialize(
918        runtime: &ConjureRuntime,
919        request_headers: &HeaderMap,
920        value: T,
921    ) -> Result<Response<LocalAsyncResponseBody<W>>, Error> {
922        Self::serialize_inner(
923            runtime,
924            request_headers,
925            &value,
926            LocalAsyncResponseBody::Fixed,
927        )
928    }
929}
930
931/// A trait implemented by header decoders used by custom Conjure server trait implementations.
932pub trait DecodeHeader<T> {
933    /// Decodes the value from headers.
934    fn decode<'a, I>(runtime: &ConjureRuntime, headers: I) -> Result<T, Error>
935    where
936        I: IntoIterator<Item = &'a HeaderValue>;
937}
938
939/// A trait implemented by URL parameter decoders used by custom Conjure server trait
940/// implementations.
941pub trait DecodeParam<T> {
942    /// Decodes the value from the sequence of values.
943    ///
944    /// The values have already been percent-decoded.
945    fn decode<I>(runtime: &ConjureRuntime, params: I) -> Result<T, Error>
946    where
947        I: IntoIterator,
948        I::Item: AsRef<str>;
949}
950
951/// A decoder which converts a single value using its [`FromStr`] implementation.
952pub enum FromStrDecoder {}
953
954impl<T> DecodeHeader<T> for FromStrDecoder
955where
956    T: FromStr,
957    T::Err: Into<Box<dyn error::Error + Sync + Send>>,
958{
959    fn decode<'a, I>(_: &ConjureRuntime, headers: I) -> Result<T, Error>
960    where
961        I: IntoIterator<Item = &'a HeaderValue>,
962    {
963        only_item(headers)?
964            .to_str()
965            .map_err(|e| Error::service(e, InvalidArgument::new()))?
966            .parse()
967            .map_err(|e| Error::service(e, InvalidArgument::new()))
968    }
969}
970
971impl<T> DecodeParam<T> for FromStrDecoder
972where
973    T: FromStr,
974    T::Err: Into<Box<dyn error::Error + Sync + Send>>,
975{
976    fn decode<I>(_: &ConjureRuntime, params: I) -> Result<T, Error>
977    where
978        I: IntoIterator,
979        I::Item: AsRef<str>,
980    {
981        only_item(params)?
982            .as_ref()
983            .parse()
984            .map_err(|e| Error::service(e, InvalidArgument::new()))
985    }
986}
987
988/// A decoder which converts an optional value using its [`FromStr`] implementation.
989pub enum FromStrOptionDecoder {}
990
991impl<T> DecodeHeader<Option<T>> for FromStrOptionDecoder
992where
993    T: FromStr,
994    T::Err: Into<Box<dyn error::Error + Sync + Send>>,
995{
996    fn decode<'a, I>(_: &ConjureRuntime, headers: I) -> Result<Option<T>, Error>
997    where
998        I: IntoIterator<Item = &'a HeaderValue>,
999    {
1000        let Some(header) = optional_item(headers)? else {
1001            return Ok(None);
1002        };
1003        let value = header
1004            .to_str()
1005            .map_err(|e| Error::service(e, InvalidArgument::new()))?
1006            .parse()
1007            .map_err(|e| Error::service(e, InvalidArgument::new()))?;
1008        Ok(Some(value))
1009    }
1010}
1011
1012impl<T> DecodeParam<Option<T>> for FromStrOptionDecoder
1013where
1014    T: FromStr,
1015    T::Err: Into<Box<dyn error::Error + Sync + Send>>,
1016{
1017    fn decode<I>(_: &ConjureRuntime, params: I) -> Result<Option<T>, Error>
1018    where
1019        I: IntoIterator,
1020        I::Item: AsRef<str>,
1021    {
1022        let Some(param) = optional_item(params)? else {
1023            return Ok(None);
1024        };
1025        let value = param
1026            .as_ref()
1027            .parse()
1028            .map_err(|e| Error::service(e, InvalidArgument::new()))?;
1029        Ok(Some(value))
1030    }
1031}
1032
1033fn optional_item<I>(it: I) -> Result<Option<I::Item>, Error>
1034where
1035    I: IntoIterator,
1036{
1037    let mut it = it.into_iter();
1038    let Some(item) = it.next() else {
1039        return Ok(None);
1040    };
1041
1042    let remaining = it.count();
1043    if remaining > 0 {
1044        return Err(
1045            Error::service_safe("expected at most 1 parameter", InvalidArgument::new())
1046                .with_safe_param("actual", remaining + 1),
1047        );
1048    }
1049
1050    Ok(Some(item))
1051}
1052
1053/// A decoder which converts a sequence of values via its [`FromStr`] implementation into a
1054/// collection via a [`FromIterator`] implementation.
1055pub struct FromStrSeqDecoder<U> {
1056    _p: PhantomData<U>,
1057}
1058
1059impl<T, U> DecodeParam<T> for FromStrSeqDecoder<U>
1060where
1061    T: FromIterator<U>,
1062    U: FromStr,
1063    U::Err: Into<Box<dyn error::Error + Sync + Send>>,
1064{
1065    fn decode<I>(_: &ConjureRuntime, params: I) -> Result<T, Error>
1066    where
1067        I: IntoIterator,
1068        I::Item: AsRef<str>,
1069    {
1070        params
1071            .into_iter()
1072            .map(|s| {
1073                s.as_ref()
1074                    .parse()
1075                    .map_err(|e| Error::service(e, InvalidArgument::new()))
1076            })
1077            .collect()
1078    }
1079}
1080
1081fn only_item<I>(it: I) -> Result<I::Item, Error>
1082where
1083    I: IntoIterator,
1084{
1085    let mut it = it.into_iter();
1086    let Some(item) = it.next() else {
1087        return Err(
1088            Error::service_safe("expected exactly 1 parameter", InvalidArgument::new())
1089                .with_safe_param("actual", 0),
1090        );
1091    };
1092
1093    let remaining = it.count();
1094    if remaining > 0 {
1095        return Err(
1096            Error::service_safe("expected exactly 1 parameter", InvalidArgument::new())
1097                .with_safe_param("actual", remaining + 1),
1098        );
1099    }
1100
1101    Ok(item)
1102}
1103
1104/// A decoder which maps the output of another with [`From::from`].
1105pub struct FromDecoder<D, U> {
1106    _p: PhantomData<(D, U)>,
1107}
1108
1109impl<T, D, U> DecodeParam<T> for FromDecoder<D, U>
1110where
1111    T: From<U>,
1112    D: DecodeParam<U>,
1113{
1114    fn decode<I>(runtime: &ConjureRuntime, params: I) -> Result<T, Error>
1115    where
1116        I: IntoIterator,
1117        I::Item: AsRef<str>,
1118    {
1119        D::decode(runtime, params).map(T::from)
1120    }
1121}
1122
1123impl<T, D, U> DecodeHeader<T> for FromDecoder<D, U>
1124where
1125    T: From<U>,
1126    D: DecodeHeader<U>,
1127{
1128    fn decode<'a, I>(runtime: &ConjureRuntime, headers: I) -> Result<T, Error>
1129    where
1130        I: IntoIterator<Item = &'a HeaderValue>,
1131    {
1132        D::decode(runtime, headers).map(T::from)
1133    }
1134}