use super::OpenApiResponderInner;
use crate::{
gen::OpenApiGenerator,
util::{
add_default_response_code, add_schema_response, change_all_responses_to_default,
ensure_status_code_exists, produce_any_responses, set_content_type, set_status_code,
},
};
use okapi::openapi3::Responses;
use rocket::serde::json::{Json, Value};
use schemars::JsonSchema;
use serde::Serialize;
use std::sync::Arc;
type Result = crate::Result<Responses>;
impl OpenApiResponderInner for &str {
fn responses(gen: &mut OpenApiGenerator) -> Result {
<String>::responses(gen)
}
}
impl OpenApiResponderInner for Arc<str> {
fn responses(gen: &mut OpenApiGenerator) -> Result {
<String>::responses(gen)
}
}
impl OpenApiResponderInner for &[u8] {
fn responses(gen: &mut OpenApiGenerator) -> Result {
<Vec<u8>>::responses(gen)
}
}
impl OpenApiResponderInner for Arc<[u8]> {
fn responses(gen: &mut OpenApiGenerator) -> Result {
<Vec<u8>>::responses(gen)
}
}
impl OpenApiResponderInner for std::fs::File {
fn responses(gen: &mut OpenApiGenerator) -> Result {
<Vec<u8>>::responses(gen)
}
}
impl OpenApiResponderInner for rocket::tokio::fs::File {
fn responses(gen: &mut OpenApiGenerator) -> Result {
<Vec<u8>>::responses(gen)
}
}
impl OpenApiResponderInner for () {
fn responses(_: &mut OpenApiGenerator) -> Result {
let mut responses = Responses::default();
ensure_status_code_exists(&mut responses, 200);
Ok(responses)
}
}
impl<'r, 'o: 'r, T> OpenApiResponderInner for std::borrow::Cow<'o, T>
where
T: OpenApiResponderInner + Clone,
{
fn responses(gen: &mut OpenApiGenerator) -> Result {
let mut responses = T::responses(gen)?;
ensure_status_code_exists(&mut responses, 200);
Ok(responses)
}
}
impl<L, R> OpenApiResponderInner for either::Either<L, R>
where
L: OpenApiResponderInner,
R: OpenApiResponderInner,
{
fn responses(gen: &mut OpenApiGenerator) -> Result {
let left_responses = L::responses(gen)?;
let right_responses = R::responses(gen)?;
produce_any_responses(left_responses, right_responses)
}
}
impl OpenApiResponderInner for std::io::Error {
fn responses(_gen: &mut OpenApiGenerator) -> Result {
let mut responses = Responses::default();
ensure_status_code_exists(&mut responses, 500);
Ok(responses)
}
}
impl<R: OpenApiResponderInner> OpenApiResponderInner for (rocket::http::ContentType, R) {
fn responses(gen: &mut OpenApiGenerator) -> Result {
let mut responses = R::responses(gen)?;
set_content_type(&mut responses, rocket::http::ContentType::Any)?;
Ok(responses)
}
}
impl<R: OpenApiResponderInner> OpenApiResponderInner for (rocket::http::Status, R) {
fn responses(gen: &mut OpenApiGenerator) -> Result {
let mut responses = R::responses(gen)?;
change_all_responses_to_default(&mut responses);
Ok(responses)
}
}
impl OpenApiResponderInner for Value {
fn responses(_gen: &mut OpenApiGenerator) -> Result {
let mut responses = Responses::default();
let schema = schemars::schema::Schema::Bool(true);
add_schema_response(&mut responses, 200, "application/json", schema.into())?;
Ok(responses)
}
}
impl OpenApiResponderInner for rocket::fs::NamedFile {
fn responses(gen: &mut OpenApiGenerator) -> Result {
<Vec<u8>>::responses(gen)
}
}
impl OpenApiResponderInner for rocket::http::Status {
fn responses(_gen: &mut OpenApiGenerator) -> Result {
let mut responses = Responses::default();
add_default_response_code(&mut responses);
Ok(responses)
}
}
impl OpenApiResponderInner for Box<[u8]> {
fn responses(gen: &mut OpenApiGenerator) -> Result {
<Vec<u8>>::responses(gen)
}
}
impl OpenApiResponderInner for Box<str> {
fn responses(gen: &mut OpenApiGenerator) -> Result {
<String>::responses(gen)
}
}
impl OpenApiResponderInner for String {
fn responses(gen: &mut OpenApiGenerator) -> Result {
let mut responses = Responses::default();
let schema = gen.json_schema::<String>();
add_schema_response(&mut responses, 200, "text/plain", schema)?;
Ok(responses)
}
}
impl OpenApiResponderInner for Vec<u8> {
fn responses(gen: &mut OpenApiGenerator) -> Result {
let mut responses = Responses::default();
let schema = gen.json_schema::<Vec<u8>>();
add_schema_response(&mut responses, 200, "application/octet-stream", schema)?;
Ok(responses)
}
}
impl OpenApiResponderInner for rocket::response::status::NoContent {
fn responses(_gen: &mut OpenApiGenerator) -> Result {
let mut responses = Responses::default();
set_status_code(&mut responses, 204)?;
Ok(responses)
}
}
impl OpenApiResponderInner for rocket::response::Redirect {
fn responses(_gen: &mut OpenApiGenerator) -> Result {
let mut responses = Responses::default();
set_status_code(&mut responses, 301)?; set_status_code(&mut responses, 302)?; set_status_code(&mut responses, 303)?; set_status_code(&mut responses, 307)?; set_status_code(&mut responses, 308)?; set_status_code(&mut responses, 500)?; Ok(responses)
}
}
impl<T, E> OpenApiResponderInner for std::result::Result<T, E>
where
T: OpenApiResponderInner,
E: OpenApiResponderInner,
{
fn responses(gen: &mut OpenApiGenerator) -> Result {
let ok_responses = T::responses(gen)?;
let err_responses = E::responses(gen)?;
produce_any_responses(ok_responses, err_responses)
}
}
impl<T: OpenApiResponderInner> OpenApiResponderInner for Option<T> {
fn responses(gen: &mut OpenApiGenerator) -> Result {
let mut responses = T::responses(gen)?;
ensure_status_code_exists(&mut responses, 404);
Ok(responses)
}
}
macro_rules! response_content_wrapper {
($responder: ident, $mime: literal) => {
impl<T: OpenApiResponderInner> OpenApiResponderInner
for rocket::response::content::$responder<T>
{
fn responses(gen: &mut OpenApiGenerator) -> Result {
let mut responses = T::responses(gen)?;
set_content_type(&mut responses, $mime)?;
Ok(responses)
}
}
};
}
response_content_wrapper!(RawCss, "text/css");
response_content_wrapper!(RawHtml, "text/html");
response_content_wrapper!(RawJavaScript, "application/javascript");
response_content_wrapper!(RawJson, "application/json");
response_content_wrapper!(RawMsgPack, "application/msgpack");
response_content_wrapper!(RawText, "text/plain");
response_content_wrapper!(RawXml, "text/xml");
macro_rules! status_responder {
($responder: ident, $status: literal) => {
impl<T> OpenApiResponderInner for rocket::response::status::$responder<T>
where
T: OpenApiResponderInner + Send,
{
fn responses(gen: &mut OpenApiGenerator) -> Result {
let mut responses = T::responses(gen)?;
set_status_code(&mut responses, $status)?;
Ok(responses)
}
}
};
}
status_responder!(Accepted, 202);
status_responder!(BadRequest, 400);
status_responder!(Conflict, 409);
status_responder!(Created, 201);
status_responder!(Custom, 0);
status_responder!(Forbidden, 403);
status_responder!(NotFound, 404);
status_responder!(Unauthorized, 401);
impl<R> OpenApiResponderInner for rocket::response::Flash<R>
where
R: OpenApiResponderInner,
{
fn responses(gen: &mut OpenApiGenerator) -> Result {
R::responses(gen)
}
}
impl<R> OpenApiResponderInner for rocket::data::Capped<R>
where
R: OpenApiResponderInner,
{
fn responses(gen: &mut OpenApiGenerator) -> Result {
R::responses(gen)
}
}
impl<E> OpenApiResponderInner for rocket::response::Debug<E>
where
E: std::fmt::Debug,
{
fn responses(_gen: &mut OpenApiGenerator) -> Result {
let mut responses = Responses::default();
set_status_code(&mut responses, 500)?;
Ok(responses)
}
}
impl<S> OpenApiResponderInner for rocket::response::stream::ByteStream<S>
where
S: Send,
{
fn responses(gen: &mut OpenApiGenerator) -> Result {
<Vec<u8>>::responses(gen)
}
}
impl<S> OpenApiResponderInner for rocket::response::stream::ReaderStream<S>
where
S: Send + rocket::futures::Stream,
{
fn responses(_gen: &mut OpenApiGenerator) -> Result {
let mut responses = Responses::default();
ensure_status_code_exists(&mut responses, 200);
Ok(responses)
}
}
impl<S> OpenApiResponderInner for rocket::response::stream::TextStream<S>
where
S: Send,
{
fn responses(gen: &mut OpenApiGenerator) -> Result {
let mut responses = Responses::default();
let schema = gen.json_schema::<&str>();
add_schema_response(&mut responses, 200, "text/plain; charset=utf-8", schema)?;
Ok(responses)
}
}
impl<S> OpenApiResponderInner for rocket::response::stream::EventStream<S> {
fn responses(gen: &mut OpenApiGenerator) -> Result {
let mut responses = Responses::default();
let schema = gen.json_schema::<Vec<u8>>();
add_schema_response(&mut responses, 200, "text/event-stream", schema)?;
Ok(responses)
}
}
impl<T: Serialize + JsonSchema + Send> OpenApiResponderInner for Json<T> {
fn responses(gen: &mut OpenApiGenerator) -> Result {
let mut responses = Responses::default();
let schema = gen.json_schema::<T>();
add_schema_response(&mut responses, 200, "application/json", schema)?;
Ok(responses)
}
}
#[cfg(feature = "msgpack")]
impl<T: Serialize + JsonSchema + Send> OpenApiResponderInner
for rocket::serde::msgpack::MsgPack<T>
{
fn responses(gen: &mut OpenApiGenerator) -> Result {
let mut responses = Responses::default();
let schema = gen.json_schema::<T>();
add_schema_response(&mut responses, 200, "application/msgpack", schema)?;
Ok(responses)
}
}
#[cfg(feature = "rocket_dyn_templates")]
impl OpenApiResponderInner for rocket_dyn_templates::Template {
fn responses(gen: &mut OpenApiGenerator) -> Result {
String::responses(gen)
}
}