Created
October 1, 2020 11:03
-
-
Save platy/e0bc44e0ce91c8268dcf0d9689e1f974 to your computer and use it in GitHub Desktop.
Changing status codes in paperclip actix-web plugin
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::fmt; | |
use actix_http::{Response, Error}; | |
use actix_web::{HttpRequest, Responder}; | |
use actix_web::http::StatusCode; | |
use futures::future::{err, ok, Ready}; | |
use paperclip::v2::schema::Apiv2Schema; | |
use paperclip::actix::OperationModifier; | |
use paperclip::v2::models::{Response as PaperclipResponse, Either, DefaultOperationRaw, DefaultSchemaRaw}; | |
use serde::Serialize; | |
macro_rules! json_with_status { | |
($name:ident => $status:expr) => { | |
pub struct $name<T: Serialize + Apiv2Schema>(pub T); | |
impl<T> fmt::Debug for $name<T> | |
where | |
T: fmt::Debug + Serialize + Apiv2Schema, | |
{ | |
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
let status: StatusCode = $status; | |
let status_str = status.canonical_reason().unwrap_or(status.as_str()); | |
write!(f, "{} Json: {:?}", status_str, self.0) | |
} | |
} | |
impl<T> fmt::Display for $name<T> | |
where | |
T: fmt::Display + Serialize + Apiv2Schema, | |
{ | |
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
fmt::Display::fmt(&self.0, f) | |
} | |
} | |
impl<T> Responder for $name<T> | |
where | |
T: Serialize + Apiv2Schema, | |
{ | |
type Error = Error; | |
type Future = Ready<Result<Response, Error>>; | |
fn respond_to(self, _: &HttpRequest) -> Self::Future { | |
let body = match serde_json::to_string(&self.0) { | |
Ok(body) => body, | |
Err(e) => return err(e.into()), | |
}; | |
ok(Response::build(StatusCode::CREATED) | |
.content_type("application/json") | |
.body(body)) | |
} | |
} | |
impl<T> Apiv2Schema for $name<T> | |
where | |
T: Serialize + Apiv2Schema, | |
{ | |
const NAME: Option<&'static str> = T::NAME; | |
fn raw_schema() -> DefaultSchemaRaw { | |
T::raw_schema() | |
} | |
} | |
impl<T> OperationModifier for $name<T> | |
where | |
T: Serialize + Apiv2Schema, | |
{ | |
fn update_response(op: &mut DefaultOperationRaw) { | |
let status: StatusCode = $status; | |
op.responses.insert( | |
status.as_str().into(), | |
Either::Right(PaperclipResponse { | |
description: status.canonical_reason().map(ToString::to_string), | |
schema: Some({ | |
let mut def = T::schema_with_ref(); | |
def.retain_ref(); | |
def | |
}), | |
..Default::default() | |
}), | |
); | |
} | |
} | |
}; | |
} | |
json_with_status!(CreatedJson => StatusCode::CREATED); | |
json_with_status!(AcceptedJson => StatusCode::ACCEPTED); | |
#[derive(Debug)] | |
pub struct NoContent; | |
impl fmt::Display for NoContent { | |
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
f.write_str("No Content") | |
} | |
} | |
impl Responder for NoContent { | |
type Error = Error; | |
type Future = Ready<Result<Response, Error>>; | |
fn respond_to(self, _: &HttpRequest) -> Self::Future { | |
ok(Response::build(StatusCode::NO_CONTENT) | |
.content_type("application/json") | |
.finish()) | |
} | |
} | |
impl Apiv2Schema for NoContent {} | |
impl OperationModifier for NoContent { | |
fn update_response(op: &mut DefaultOperationRaw) { | |
let status = StatusCode::NO_CONTENT; | |
op.responses.insert( | |
status.as_str().into(), | |
Either::Right(PaperclipResponse { | |
description: status.canonical_reason().map(ToString::to_string), | |
schema: None, | |
..Default::default() | |
}), | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment