Fix error codes, handle bad requests for creation

Fix that invalid UTF-8 or continuing the read mid-character crashes
server thread.
This commit is contained in:
Schrottkatze 2023-03-10 08:18:11 +01:00
parent 1652a850b8
commit 42aceb2a01
8 changed files with 65 additions and 24 deletions

View file

@ -5,6 +5,8 @@ use crate::util::misc::is_valid_url;
use crate::util::pasta_id_converter::CONVERTER; use crate::util::pasta_id_converter::CONVERTER;
use crate::{AppState, Pasta, ARGS}; use crate::{AppState, Pasta, ARGS};
use actix_multipart::Multipart; use actix_multipart::Multipart;
use actix_web::http::StatusCode;
use actix_web::web::{Bytes, BytesMut, BufMut};
use actix_web::{get, web, Error, HttpResponse, Responder}; use actix_web::{get, web, Error, HttpResponse, Responder};
use askama::Template; use askama::Template;
use bytesize::ByteSize; use bytesize::ByteSize;
@ -14,6 +16,8 @@ use rand::Rng;
use std::io::Write; use std::io::Write;
use std::time::{SystemTime, UNIX_EPOCH}; use std::time::{SystemTime, UNIX_EPOCH};
use super::errors::ErrorTemplate;
#[derive(Template)] #[derive(Template)]
#[template(path = "index.html")] #[template(path = "index.html")]
struct IndexTemplate<'a> { struct IndexTemplate<'a> {
@ -115,12 +119,20 @@ pub async fn create(
} }
} }
"content" => { "content" => {
let mut content = String::from(""); let mut content = BytesMut::new();
while let Some(chunk) = field.try_next().await? { while let Some(chunk) = field.try_next().await? {
content.push_str(std::str::from_utf8(&chunk).unwrap().to_string().as_str()); content.put(chunk);
} }
if !content.is_empty() { if !content.is_empty() {
new_pasta.content = content; new_pasta.content = match String::from_utf8(content.to_vec()) {
Ok(v) => v,
Err(e) => return Ok(HttpResponse::BadRequest()
.content_type("text/html")
.body(ErrorTemplate {
status_code: StatusCode::BAD_REQUEST,
args: &ARGS
}.render().unwrap())),
};
new_pasta.pasta_type = if is_valid_url(new_pasta.content.as_str()) { new_pasta.pasta_type = if is_valid_url(new_pasta.content.as_str()) {
String::from("url") String::from("url")

View file

@ -6,6 +6,7 @@ use crate::util::misc::remove_expired;
use crate::util::pasta_id_converter::CONVERTER; use crate::util::pasta_id_converter::CONVERTER;
use crate::{AppState, Pasta, ARGS}; use crate::{AppState, Pasta, ARGS};
use actix_multipart::Multipart; use actix_multipart::Multipart;
use actix_web::http::StatusCode;
use actix_web::{get, post, web, Error, HttpResponse}; use actix_web::{get, post, web, Error, HttpResponse};
use askama::Template; use askama::Template;
use futures::TryStreamExt; use futures::TryStreamExt;
@ -42,9 +43,12 @@ pub async fn get_edit(data: web::Data<AppState>, id: web::Path<String>) -> HttpR
} }
} }
HttpResponse::Ok() HttpResponse::NotFound()
.content_type("text/html") .content_type("text/html")
.body(ErrorTemplate { args: &ARGS }.render().unwrap()) .body(ErrorTemplate {
status_code: StatusCode::NOT_FOUND,
args: &ARGS
}.render().unwrap())
} }
#[post("/edit/{id}")] #[post("/edit/{id}")]
@ -97,7 +101,10 @@ pub async fn post_edit(
} }
} }
Ok(HttpResponse::Ok() Ok(HttpResponse::NotFound()
.content_type("text/html") .content_type("text/html")
.body(ErrorTemplate { args: &ARGS }.render().unwrap())) .body(ErrorTemplate {
status_code: StatusCode::NOT_FOUND,
args: &ARGS
}.render().unwrap()))
} }

View file

@ -1,4 +1,4 @@
use actix_web::{Error, HttpResponse}; use actix_web::{Error, HttpResponse, http::StatusCode};
use askama::Template; use askama::Template;
use crate::args::{Args, ARGS}; use crate::args::{Args, ARGS};
@ -6,11 +6,15 @@ use crate::args::{Args, ARGS};
#[derive(Template)] #[derive(Template)]
#[template(path = "error.html")] #[template(path = "error.html")]
pub struct ErrorTemplate<'a> { pub struct ErrorTemplate<'a> {
pub status_code: StatusCode,
pub args: &'a Args, pub args: &'a Args,
} }
pub async fn not_found() -> Result<HttpResponse, Error> { pub async fn not_found() -> Result<HttpResponse, Error> {
Ok(HttpResponse::Ok() Ok(HttpResponse::NotFound()
.content_type("text/html") .content_type("text/html")
.body(ErrorTemplate { args: &ARGS }.render().unwrap())) .body(ErrorTemplate {
status_code: StatusCode::NOT_FOUND,
args: &ARGS
}.render().unwrap()))
} }

View file

@ -7,6 +7,7 @@ use crate::util::misc::remove_expired;
use crate::AppState; use crate::AppState;
use crate::util::pasta_id_converter::CONVERTER; use crate::util::pasta_id_converter::CONVERTER;
use actix_web::http::StatusCode;
use actix_web::{web, HttpResponse}; use actix_web::{web, HttpResponse};
use askama::Template; use askama::Template;
use std::time::{SystemTime, UNIX_EPOCH}; use std::time::{SystemTime, UNIX_EPOCH};
@ -77,9 +78,12 @@ pub async fn getpasta(data: web::Data<AppState>, id: web::Path<String>) -> HttpR
// otherwise // otherwise
// send pasta not found error // send pasta not found error
HttpResponse::Ok() HttpResponse::NotFound()
.content_type("text/html") .content_type("text/html")
.body(ErrorTemplate { args: &ARGS }.render().unwrap()) .body(ErrorTemplate {
status_code: StatusCode::NOT_FOUND,
args: &ARGS
}.render().unwrap())
} }
/// Endpoint for redirection. /// Endpoint for redirection.
@ -136,17 +140,23 @@ pub async fn redirecturl(data: web::Data<AppState>, id: web::Path<String>) -> Ht
return response; return response;
// send error if we're trying to open a non-url pasta as a redirect // send error if we're trying to open a non-url pasta as a redirect
} else { } else {
HttpResponse::Ok() HttpResponse::NotFound()
.content_type("text/html") .content_type("text/html")
.body(ErrorTemplate { args: &ARGS }.render().unwrap()); .body(ErrorTemplate {
status_code: StatusCode::NOT_FOUND,
args: &ARGS
}.render().unwrap());
} }
} }
// otherwise // otherwise
// send pasta not found error // send pasta not found error
HttpResponse::Ok() HttpResponse::NotFound()
.content_type("text/html") .content_type("text/html")
.body(ErrorTemplate { args: &ARGS }.render().unwrap()) .body(ErrorTemplate {
status_code: StatusCode::NOT_FOUND,
args: &ARGS
}.render().unwrap())
} }
/// Endpoint to request pasta as raw file. /// Endpoint to request pasta as raw file.

View file

@ -5,6 +5,7 @@ use crate::util::hashids::to_u64 as hashid_to_u64;
use crate::util::misc::{self, remove_expired}; use crate::util::misc::{self, remove_expired};
use crate::AppState; use crate::AppState;
use crate::util::pasta_id_converter::CONVERTER; use crate::util::pasta_id_converter::CONVERTER;
use actix_web::http::StatusCode;
use actix_web::{get, web, HttpResponse}; use actix_web::{get, web, HttpResponse};
use askama::Template; use askama::Template;
@ -63,7 +64,10 @@ pub async fn getqr(data: web::Data<AppState>, id: web::Path<String>) -> HttpResp
// otherwise // otherwise
// send pasta not found error // send pasta not found error
HttpResponse::Ok() HttpResponse::NotFound()
.content_type("text/html") .content_type("text/html")
.body(ErrorTemplate { args: &ARGS }.render().unwrap()) .body(ErrorTemplate {
status_code: StatusCode::NOT_FOUND,
args: &ARGS
}.render().unwrap())
} }

View file

@ -1,3 +1,4 @@
use actix_web::http::StatusCode;
use actix_web::{get, web, HttpResponse}; use actix_web::{get, web, HttpResponse};
use crate::args::ARGS; use crate::args::ARGS;
@ -58,7 +59,10 @@ pub async fn remove(data: web::Data<AppState>, id: web::Path<String>) -> HttpRes
remove_expired(&mut pastas); remove_expired(&mut pastas);
HttpResponse::Ok() HttpResponse::NotFound()
.content_type("text/html") .content_type("text/html")
.body(ErrorTemplate { args: &ARGS }.render().unwrap()) .body(ErrorTemplate {
status_code: StatusCode::NOT_FOUND,
args: &ARGS
}.render().unwrap())
} }

View file

@ -1,7 +1,7 @@
{% include "header.html" %} {% include "header.html" %}
<br> <br>
<h2>404</h2> <h2>{{ status_code.as_u16() }}</h2>
<b>Not Found</b> <b>{{ status_code.canonical_reason().unwrap_or("Unknown error") }}</b>
<br> <br>
<br> <br>
<a href="{{ args.public_path }}/"> Go Home</a> <a href="{{ args.public_path }}/"> Go Home</a>

View file

@ -2,7 +2,7 @@
<html> <html>
<head> <head>
<title>MicroBin</title> <title>{{ args.title }}</title>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">