Skip to content

Commit

Permalink
fix: fixed support for paths with url encodings
Browse files Browse the repository at this point in the history
For a page with a space in it, which would be encoded as `%20`, Perseus
was completely unable to handle this --- it now can!
  • Loading branch information
arctic-hen7 committed Nov 4, 2022
1 parent 6a9c9c7 commit a329952
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,6 @@ pub async fn get_build_paths() -> RenderFnResult<Vec<String>> {
"".to_string(),
"test".to_string(),
"blah/test/blah".to_string(),
"a test".to_string(), // Perseus caan even handle paths with special characters!
])
}
16 changes: 15 additions & 1 deletion packages/perseus-actix-web/src/initial_load.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::conv_req::convert_req;
use actix_web::{http::StatusCode, web, HttpRequest, HttpResponse};
use fmterr::fmt_err;
use perseus::{
errors::err_to_status_code,
errors::{err_to_status_code, ServerError},
i18n::{TranslationsManager, Translator},
router::{match_route_atomic, RouteInfoAtomic, RouteVerdictAtomic},
server::{
Expand Down Expand Up @@ -49,6 +49,20 @@ pub async fn initial_load<M: MutableStore, T: TranslationsManager>(
let templates = &opts.templates_map;
let error_pages = &opts.error_pages;
let path = req.path();
let path = match urlencoding::decode(path) {
Ok(path) => path.to_string(),
Err(err) => {
return return_error_page(
path,
400,
&fmt_err(&ServerError::UrlDecodeFailed { source: err }),
None,
error_pages,
html_shell.as_ref(),
)
}
};
let path = path.as_str();
let path_slice = get_path_slice(path);
// Create a closure to make returning error pages easier (most have the same
// data)
Expand Down
18 changes: 16 additions & 2 deletions packages/perseus-axum/src/initial_load.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use axum::{
};
use fmterr::fmt_err;
use perseus::{
errors::err_to_status_code,
errors::{err_to_status_code, ServerError},
i18n::{TranslationsManager, Translator},
router::{match_route_atomic, RouteInfoAtomic, RouteVerdictAtomic},
server::{
Expand Down Expand Up @@ -50,11 +50,25 @@ pub async fn initial_load_handler<M: MutableStore, T: TranslationsManager>(
translations_manager: Arc<T>,
global_state: Arc<Option<String>>,
) -> (StatusCode, HeaderMap, Html<String>) {
let error_pages = &opts.error_pages;
let path = http_req.uri().path().to_string();
let path = match urlencoding::decode(&path) {
Ok(path) => path.to_string(),
Err(err) => {
return return_error_page(
path.as_str(),
400,
&fmt_err(&ServerError::UrlDecodeFailed { source: err }),
None,
error_pages,
html_shell.as_ref(),
)
}
};
let path = path.as_str();
let http_req = Request::from_parts(http_req.into_parts().0, ());

let templates = &opts.templates_map;
let error_pages = &opts.error_pages;
let path_slice = get_path_slice(&path);
// Create a closure to make returning error pages easier (most have the same
// data)
Expand Down
17 changes: 15 additions & 2 deletions packages/perseus-warp/src/initial_load.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use fmterr::fmt_err;
use perseus::{
errors::err_to_status_code,
errors::{err_to_status_code, ServerError},
i18n::{TranslationsManager, Translator},
router::{match_route_atomic, RouteInfoAtomic, RouteVerdictAtomic},
server::{
Expand Down Expand Up @@ -43,9 +43,22 @@ pub async fn initial_load_handler<M: MutableStore, T: TranslationsManager>(
translations_manager: Arc<T>,
global_state: Arc<Option<String>>,
) -> Response<String> {
let error_pages = &opts.error_pages;
let path = match urlencoding::decode(path.as_str()) {
Ok(path) => path.to_string(),
Err(err) => {
return return_error_page(
path.as_str(),
400,
&fmt_err(&ServerError::UrlDecodeFailed { source: err }),
None,
error_pages,
html_shell.as_ref(),
)
}
};
let path = path.as_str();
let templates = &opts.templates_map;
let error_pages = &opts.error_pages;
let path_slice = get_path_slice(path);
// Create a closure to make returning error pages easier (most have the same
// data)
Expand Down
5 changes: 5 additions & 0 deletions packages/perseus/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@ pub enum ServerError {
#[source]
source: std::io::Error,
},
#[error("failed to decode url provided (probably malformed request)")]
UrlDecodeFailed {
#[source]
source: std::string::FromUtf8Error,
},
#[error(transparent)]
GlobalStateError(#[from] GlobalStateError),
#[error(transparent)]
Expand Down
4 changes: 4 additions & 0 deletions packages/perseus/src/router/get_initial_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ pub(crate) fn get_initial_view(
let error_pages = &render_ctx.error_pages;
let pss = &render_ctx.page_state_store;

let path = js_sys::decode_uri_component(&path)
.unwrap()
.as_string()
.unwrap();
// Start by figuring out what template we should be rendering
let path_segments = path
.split('/')
Expand Down
4 changes: 4 additions & 0 deletions packages/perseus/src/router/get_subsequent_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ pub(crate) async fn get_subsequent_view(
let error_pages = &render_ctx.error_pages;
let pss = &render_ctx.page_state_store;

let path = js_sys::decode_uri_component(&path)
.unwrap()
.as_string()
.unwrap();
let path_with_locale = match locale.as_str() {
"xx-XX" => path.clone(),
locale => format!("{}/{}", locale, &path),
Expand Down

0 comments on commit a329952

Please sign in to comment.