poem_openapi/payload/
binary.rs1use std::ops::{Deref, DerefMut};
2
3use bytes::Bytes;
4use poem::{Body, FromRequest, IntoResponse, Request, RequestBody, Response, Result};
5
6use crate::{
7 payload::{ParsePayload, Payload},
8 registry::{MetaMediaType, MetaResponse, MetaResponses, MetaSchema, MetaSchemaRef, Registry},
9 ApiResponse,
10};
11
12#[derive(Debug, Clone, Eq, PartialEq)]
71pub struct Binary<T>(pub T);
72
73impl<T> Deref for Binary<T> {
74 type Target = T;
75
76 fn deref(&self) -> &Self::Target {
77 &self.0
78 }
79}
80
81impl<T> DerefMut for Binary<T> {
82 fn deref_mut(&mut self) -> &mut Self::Target {
83 &mut self.0
84 }
85}
86
87impl<T: Send> Payload for Binary<T> {
88 const CONTENT_TYPE: &'static str = "application/octet-stream";
89
90 fn check_content_type(content_type: &str) -> bool {
91 matches!(content_type.parse::<mime::Mime>(), Ok(content_type) if content_type.type_() == "application"
92 && (content_type.subtype() == "octet-stream"
93 || content_type
94 .suffix()
95 .is_some_and(|v| v == "octet-stream")))
96 }
97
98 fn schema_ref() -> MetaSchemaRef {
99 MetaSchemaRef::Inline(Box::new(MetaSchema {
100 format: Some("binary"),
101 ..MetaSchema::new("string")
102 }))
103 }
104}
105
106impl ParsePayload for Binary<Vec<u8>> {
107 const IS_REQUIRED: bool = true;
108
109 async fn from_request(request: &Request, body: &mut RequestBody) -> Result<Self> {
110 Ok(Self(<Vec<u8>>::from_request(request, body).await?))
111 }
112}
113
114impl ParsePayload for Binary<Bytes> {
115 const IS_REQUIRED: bool = true;
116
117 async fn from_request(request: &Request, body: &mut RequestBody) -> Result<Self> {
118 Ok(Self(Bytes::from_request(request, body).await?))
119 }
120}
121
122impl ParsePayload for Binary<Body> {
123 const IS_REQUIRED: bool = true;
124
125 async fn from_request(request: &Request, body: &mut RequestBody) -> Result<Self> {
126 Ok(Self(Body::from_request(request, body).await?))
127 }
128}
129
130impl<T: Into<Body> + Send> IntoResponse for Binary<T> {
131 fn into_response(self) -> Response {
132 Response::builder()
133 .content_type(Self::CONTENT_TYPE)
134 .body(self.0.into())
135 }
136}
137
138impl<T: Into<Body> + Send> ApiResponse for Binary<T> {
139 fn meta() -> MetaResponses {
140 MetaResponses {
141 responses: vec![MetaResponse {
142 description: "",
143 status: Some(200),
144 status_range: None,
145 content: vec![MetaMediaType {
146 content_type: Self::CONTENT_TYPE,
147 schema: Self::schema_ref(),
148 }],
149 headers: vec![],
150 }],
151 }
152 }
153
154 fn register(_registry: &mut Registry) {}
155}
156
157impl_apirequest_for_payload!(Binary<Vec<u8>>);
158impl_apirequest_for_payload!(Binary<Bytes>);
159impl_apirequest_for_payload!(Binary<Body>);