Add rewrite_path()

This commit is contained in:
Emii Tatsuo 2020-12-01 19:02:49 -05:00
parent 6400197514
commit 723986c011
Signed by: Emi
GPG key ID: 68FAB2E2E6DFC98B

View file

@ -4,6 +4,7 @@ use std::convert::TryInto;
use std::{
collections::HashMap,
convert::TryFrom,
path::Path,
};
use anyhow::*;
use percent_encoding::percent_decode_str;
@ -25,6 +26,8 @@ pub struct Request {
manager: UserManager,
#[cfg(feature = "scgi_srv")]
headers: HashMap<String, String>,
#[cfg(feature = "scgi_srv")]
script_path: Option<String>,
}
impl Request {
@ -37,7 +40,7 @@ impl Request {
manager: UserManager,
) -> Result<Self> {
#[cfg(feature = "scgi_srv")]
let (mut uri, certificate) = (
let (mut uri, certificate, script_path) = (
URIReference::try_from(
format!(
"{}{}",
@ -58,6 +61,9 @@ impl Request {
.try_into()
.expect("Received certificate fingerprint of invalid lenght from upstream")
}),
headers.get("SCRIPT_PATH")
.or_else(|| headers.get("SCRIPT_NAME"))
.cloned()
);
uri.normalize();
@ -83,6 +89,8 @@ impl Request {
trailing_segments: None,
#[cfg(feature = "scgi_srv")]
headers,
#[cfg(feature = "scgi_srv")]
script_path,
#[cfg(feature="user_management")]
manager,
})
@ -192,6 +200,40 @@ impl Request {
pub fn user_manager(&self) -> &UserManager {
&self.manager
}
/// Attempt to rewrite an absolute URL against the base path of the SCGI script
///
/// When writing an SCGI script, you cannot assume that your script is mounted on the
/// base path of "/". For example, a request to the gemini server for "/app/path"
/// might be received by your script as "/path" if your script is mounted on "/app/".
/// In this situation, if you linked to "/", you would be sending users to "/", which
/// is not handled by your app, instead of "/app/", where you probably intended to
/// send the user.
///
/// This method attempts to infer where the script is mounted, and rewrite an absolute
/// url relative to that. For example, if the application was mounted on "/app/", and
/// you passed "/path", the result would be "/app/path".
///
/// When running in `gemini_srv` mode, the application is always mounted at the base
/// path, so this will always return the path unchanged.
///
/// Not all SCGI clients will correctly report the application's path, so this may
/// fail if unable to infer the correct path. If this is the case, None will be
/// returned. Currently, the SCGI headers checked are:
///
/// * `SCRIPT_PATH` (Used by mollybrown)
/// * `SCRIPT_NAME` (Used by GLV-1.12556)
pub fn rewrite_path(&self, path: impl AsRef<str>) -> Option<String> {
#[cfg(feature = "scgi_srv")] {
self.script_path.as_ref().map(|base| {
let base: &Path = base.as_ref();
base.join(path.as_ref()).display().to_string()
})
}
#[cfg(feature = "gemini_srv")] {
Some(path.to_string())
}
}
}
impl ops::Deref for Request {