use std::collections::BTreeMap; use poem::{IntoResponse, Request, RequestBody, Response, Result}; use poem_openapi::{ ApiExtractor, ApiExtractorType, ExtractParamOptions, __private::UrlQuery, payload::Payload, registry::{ MetaHeader, MetaMediaType, MetaParamIn, MetaResponse, MetaResponses, MetaSchemaRef, Registry, }, types::Type, ApiResponse, }; pub struct DynParams(pub BTreeMap); #[poem::async_trait] impl<'a> ApiExtractor<'a> for DynParams { const TYPE: ApiExtractorType = ApiExtractorType::Parameter; const PARAM_IS_REQUIRED: bool = false; type ParamType = Self; type ParamRawType = BTreeMap; fn register(registry: &mut Registry) { Self::ParamRawType::register(registry); } fn param_in() -> Option { Some(MetaParamIn::Query) } fn param_schema_ref() -> Option { Some(Self::ParamRawType::schema_ref()) } fn param_raw_type(&self) -> Option<&Self::ParamRawType> { self.0.as_raw_value() } async fn from_request( request: &'a Request, _body: &mut RequestBody, _param_opts: ExtractParamOptions, ) -> Result { Ok(Self( request .extensions() .get::() .unwrap() .0 .iter() .map(|(k, v)| (k.to_string(), v.to_string())) .collect(), )) } } pub struct FileResponse(pub Response); impl IntoResponse for FileResponse { fn into_response(self) -> Response { self.0 } } impl ApiResponse for FileResponse { fn meta() -> MetaResponses { MetaResponses { responses: vec![MetaResponse { description: "File content", status: Some(200), content: vec![MetaMediaType { content_type: "application/octet-stream", schema: poem_openapi::payload::Binary::<()>::schema_ref(), }], headers: vec![ MetaHeader { name: "etag".to_owned(), description: Some("File hash".to_owned()), required: true, deprecated: false, schema: String::schema_ref(), }, MetaHeader { name: "last-modified".to_owned(), description: Some("Date when the file was last modified".to_owned()), required: true, deprecated: false, schema: String::schema_ref(), }, ], }], } } fn register(_registry: &mut Registry) {} }