1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
use serde::{Deserialize, Serialize};
use http::StatusCode;
use axum_core::response::{Response, IntoResponse};
#[derive(Serialize, Deserialize, PartialEq, Debug)]
#[serde(rename_all = "snake_case")]
pub enum ErrorType {
/// An erroneous attempt to create something that already exists.
AlreadyExists,
/// Current user is expressly forbidden from performing this action.
Forbidden,
/// The Micropub server experienced an internal error.
InternalServerError,
/// The request was invalid or malformed.
InvalidRequest,
/// The provided OAuth2 scopes were insufficient to allow performing this action.
InvalidScope,
/// There was no token or other means of authorization in the request.
NotAuthorized,
/// Whatever was requested was not found.
NotFound,
/// The request payload was of a type unsupported by the Micropub endpoint.
UnsupportedMediaType,
}
/// Representation of the Micropub API error.
#[derive(Serialize, Deserialize, Debug)]
pub struct MicropubError {
pub error: ErrorType,
pub error_description: String,
}
impl std::error::Error for MicropubError {}
impl std::fmt::Display for MicropubError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("Micropub error: ")?;
f.write_str(&self.error_description)
}
}
impl From<serde_json::Error> for MicropubError {
fn from(err: serde_json::Error) -> Self {
use ErrorType::*;
Self {
error: InvalidRequest,
error_description: err.to_string(),
}
}
}
impl MicropubError {
pub fn new(error: ErrorType, error_description: &str) -> Self {
Self {
error,
error_description: error_description.to_owned(),
}
}
}
impl From<&MicropubError> for StatusCode {
fn from(err: &MicropubError) -> Self {
use ErrorType::*;
match err.error {
AlreadyExists => StatusCode::CONFLICT,
Forbidden => StatusCode::FORBIDDEN,
InternalServerError => StatusCode::INTERNAL_SERVER_ERROR,
InvalidRequest => StatusCode::BAD_REQUEST,
InvalidScope => StatusCode::UNAUTHORIZED,
NotAuthorized => StatusCode::UNAUTHORIZED,
NotFound => StatusCode::NOT_FOUND,
UnsupportedMediaType => StatusCode::UNSUPPORTED_MEDIA_TYPE,
}
}
}
impl From<MicropubError> for StatusCode {
fn from(err: MicropubError) -> Self {
(&err).into()
}
}
impl IntoResponse for MicropubError {
fn into_response(self) -> Response {
IntoResponse::into_response((
StatusCode::from(&self),
[("Content-Type", "application/json")],
serde_json::to_string(&self).unwrap(),
))
}
}
|