Add rewrite_path()
This commit is contained in:
parent
6400197514
commit
723986c011
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue