Skip to content

Commit

Permalink
prettier error pages
Browse files Browse the repository at this point in the history
  • Loading branch information
levkk committed Nov 11, 2024
1 parent f1a9e9d commit 9b7e349
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 103 deletions.
16 changes: 14 additions & 2 deletions examples/files/src/controllers/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use rwf::http::urlencode;
use rwf::prelude::*;

#[derive(Default, macros::PageController)]
Expand All @@ -11,8 +12,15 @@ impl PageController for Upload {

async fn post(&self, req: &Request) -> Result<Response, Error> {
let form_data = req.form_data()?;
let comment = form_data.get_required::<String>("comment")?;
if let Some(file) = form_data.file("file") {
let redirect = format!("/ok?name={}&size={}", file.name, file.body.len());
let redirect = format!(
"/ok?name={}&size={}&content_type={}&comment={}",
urlencode(file.name()),
file.body().len(),
urlencode(file.content_type()),
urlencode(&comment),
);
Ok(Response::new().redirect(redirect))
} else {
Ok(Response::bad_request())
Expand All @@ -28,10 +36,14 @@ impl Controller for UploadOk {
async fn handle(&self, req: &Request) -> Result<Response, Error> {
let name = req.query().get_required::<String>("name")?;
let size = req.query().get_required::<i64>("size")?;
let content_type = req.query().get_required::<String>("content_type")?;
let comment = req.query().get_required::<String>("comment")?;

render!("templates/ok.html",
"name" => rwf::http::urlencode(&name),
"size" => size
"size" => size,
"content_type" => content_type,
"comment" => comment,
)
}
}
8 changes: 6 additions & 2 deletions examples/files/templates/ok.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,16 @@ <h3 class="mb-4">Upload successful</h3>
<tr>
<th>File name</th>
<th>File size</th>
<th>Content type</th>
<th>Comment</th>
</tr>
</thead>
<tbody>
<tr>
<td class="pe-5"><%= name %></td>
<td class=""><%= size %> bytes</td>
<td class="pe-3"><%= name %></td>
<td class="pe-3"><%= size %> bytes</td>
<td class="pe-3"><%= content_type %></td>
<td><%= comment %></td>
</tr>
</tbody>
</table>
Expand Down
7 changes: 3 additions & 4 deletions rwf/src/controller/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,9 @@ pub trait Controller: Sync + Send {
_ => Response::internal_error(err),
},

Error::ViewError(err) => Response::internal_error_pretty(
"Template error",
err.to_string().as_str(),
),
Error::ViewError(err) => {
Response::error_pretty("Template error", err.to_string().as_str())
}

err => Response::internal_error(err),
};
Expand Down
50 changes: 39 additions & 11 deletions rwf/src/http/error.html
Original file line number Diff line number Diff line change
@@ -1,37 +1,65 @@
<!doctype html>
<html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<title><%= title %></title>
<style>
.container {
margin: 10px 25px;
body {
margin: 0;
padding: 0;
font-family: Arial, Helvetica, sans-serif;
}

.center {
.rwf-container {
padding: 10px;
}

.rwf-center {
display: flex;
align-items: center;
justify-content: center;
}

.error {
border: 1px solid red;
.rwf-error {
/* border: 1px solid red;
border-radius: 2px;
padding: 10px 30px;
padding: 10px 30px; */
}

pre {
text-wrap: wrap;
max-width: 75vw;
}

.rwf-left {
display: flex;
align-items: center;
}

.rwf-bg {
background: #CC5500;
}

.rwf-header {
margin: 0;
padding: 10px;
color: beige;
}

.rwf-footer {
margin-top: 100px;
text-align: center;
padding: 10px;
}
</style>
</head>
<body>
<div class="container center">
<h3><%= title %></h3>
<div class="rwf-left rwf-bg">
<h3 class="rwf-header"><%= title %></h3>
</div>
<% if message %>
<div class="container center">
<code class="error"><pre><%= message %></pre></code>
<div class="rwf-container rwf-left">
<code class="rwf-error"><pre><%= message %></pre></code>
</div>
<% end %>
</body>
Expand Down
24 changes: 22 additions & 2 deletions rwf/src/http/form_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ impl FormData {
.filename
.clone()
.unwrap_or("".to_string()),
content_type: f.content_type(),
}),
_ => None,
}
Expand Down Expand Up @@ -166,10 +167,29 @@ macro_rules! read_line {
/// A file uploaded via a multipart form.
#[derive(Debug, Clone)]
pub struct File<'a> {
body: &'a [u8],
name: String,
content_type: Option<String>,
}

impl File<'_> {
/// File data.
pub body: &'a [u8],
pub fn body(&self) -> &[u8] {
self.body
}

/// File name provided by the browser.
pub name: String,
pub fn name(&self) -> &str {
&self.name
}

/// Content type of the file, if provided by the browser.
pub fn content_type(&self) -> &str {
match self.content_type {
Some(ref content_type) => content_type,
None => "application/octet-stream",
}
}
}

impl Multipart {
Expand Down
97 changes: 15 additions & 82 deletions rwf/src/http/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,88 +284,36 @@ impl Response {

/// Default not found (404) error.
pub fn not_found() -> Self {
Self::new()
.html(
"
<h3>
<center>404 - Not Found</center>
</h3>
"
.trim(),
)
.code(404)
Self::error_pretty("404 - Not Found", "").code(404)
}

/// Default method not allowed (405) error.
pub fn method_not_allowed() -> Self {
Self::new()
.html(
"
<h3>
<center>405 - Method Not Allowed</center>
</h3>
",
)
.code(405)
Self::error_pretty("405 - Method Not Allowed", "").code(405)
}

pub fn bad_request() -> Self {
Self::new()
.html(
"
<h3>
<center>400 - Bad Request</center>
</h3>
",
)
.code(400)
Self::error_pretty("400 - Bad Request", "").code(400)
}

pub fn csrf_error() -> Self {
Self::new().html("
<h3>
<center>400 - Bad Request</center>
</h3>
<p>
<center>The supplied CSRF token is not valid. Reload the page to get a new one.</center>
</p>"
).code(400)
Self::error_pretty(
"400 - Bad Request",
"The supplied CSRF token is not valid. Reload the page to get a new one.",
)
.code(400)
}

pub fn not_implemented() -> Self {
Self::new()
.html(
"
<h3>
<center>501 - Not Implemented</center>
</h3>
",
)
.code(501)
Self::error_pretty("501 - Not Implemented", "").code(501)
}

pub fn forbidden() -> Self {
Self::new()
.html(
"
<h3>
<center>403 - Forbidden</center>
</h3>
",
)
.code(403)
Self::error_pretty("403 - Forbidden", "").code(403)
}

pub fn content_too_large() -> Self {
Self::new()
.html(
"
<h3>
<center>413 - Content Too Large</center>
</h3>
",
)
.code(413)
Self::error_pretty("413 - Content Too Large", "").code(413)
}

pub fn internal_error(err: impl std::error::Error) -> Self {
Expand All @@ -379,10 +327,10 @@ impl Response {
""
};

Self::internal_error_pretty("500 - Internal Server Error", &err)
Self::error_pretty("500 - Internal Server Error", &err)
}

pub fn internal_error_pretty(title: &str, message: &str) -> Self {
pub fn error_pretty(title: &str, message: &str) -> Self {
let body = ERROR_TEMPLATE
.render([("title", title), ("message", message)])
.unwrap();
Expand All @@ -391,28 +339,13 @@ impl Response {
}

pub fn unauthorized(auth: &str) -> Self {
Self::new()
.html(
"
<h3>
<center>401 - Unauthorized</center>
</h3>
",
)
Self::error_pretty("401 - Unauthorized", "")
.code(401)
.header("www-authenticate", auth)
}

pub fn too_many() -> Self {
Self::new()
.html(
"
<h3>
<center>429 - Too Many</center>
</h3>
",
)
.code(429)
Self::error_pretty("429 - Too Many", "").code(429)
}

pub fn redirect(self, to: impl ToString) -> Self {
Expand Down

0 comments on commit 9b7e349

Please sign in to comment.