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
91
92
93
|
use hyper::http::response::Builder;
use hyper::StatusCode;
use sputnik::hyper_body::FormError;
use sputnik::request::QueryError;
use sputnik::response::EmptyBuilder;
use std::str::Utf8Error;
use crate::HyperResponse;
/// For convenience this enum also contains nonerroneous variants.
pub enum Error {
/// A 400 bad request error.
BadRequest(String),
/// A 401 unauthorized error.
Unauthorized(String),
/// A 403 forbidden error.
Forbidden(String),
/// A 404 not found error.
NotFound(String),
/// A 500 internal server error.
Internal(String),
/// A 304 response.
NotModified,
/// A 302 redirect to the given path.
Redirect(String),
// TODO: use Redirect instead
/// Missing trailing slash.
MissingTrailingSlash(String),
}
impl From<Utf8Error> for Error {
fn from(_: Utf8Error) -> Self {
Self::BadRequest("invalid UTF-8".into())
}
}
impl From<git2::Error> for Error {
fn from(e: git2::Error) -> Self {
eprintln!("git error: {}", e);
Self::Internal("something went wrong with git".into())
}
}
impl From<FormError> for Error {
fn from(e: FormError) -> Self {
Self::BadRequest(e.to_string())
}
}
impl From<QueryError> for Error {
fn from(e: QueryError) -> Self {
Self::BadRequest(e.to_string())
}
}
impl From<Error> for HyperResponse {
fn from(err: Error) -> Self {
let (status, message) = match err {
Error::BadRequest(msg) => (400, msg),
Error::Unauthorized(msg) => (401, msg),
Error::Forbidden(msg) => (403, msg),
Error::NotFound(msg) => (404, msg),
Error::Internal(msg) => (500, msg),
Error::NotModified => {
return Builder::new()
.status(StatusCode::NOT_MODIFIED)
.empty()
.unwrap();
}
Error::MissingTrailingSlash(path) => {
return Builder::new()
.status(StatusCode::FOUND)
.header("location", format!("{}/", path))
.body("redirecting".into())
.unwrap();
}
Error::Redirect(target) => {
return Builder::new()
.status(StatusCode::FOUND)
.header("location", target)
.body("redirecting".into())
.unwrap();
}
};
// TODO: use Page
Builder::new()
.status(status)
.header("content-type", "text/html")
.body(message.into())
.unwrap()
}
}
|