Made the link rewriting docs *way* better

This commit is contained in:
Emi Tatsuo 2020-12-05 11:27:30 -05:00
parent 9bc1f317c5
commit 7add331e0b
Signed by: Emi
GPG key ID: 68FAB2E2E6DFC98B
3 changed files with 77 additions and 16 deletions

View file

@ -832,17 +832,65 @@ impl Server {
/// Enable or disable autorewrite
///
/// Autorewrite automatically detects links in responses being sent out through kochab
/// and rewrites them to match the base of the script. For example, if the script is
/// mounted on "/app", any links to "/page" would be rewritten as "/app/page". This
/// does nothing when in `gemini_srv` mode.
/// Many times, an app will served alongside other apps all on one domain. For
/// example:
/// * `gemini://example.com/gemlog/` might be some static content from a gemlog
/// handled by the gemini server
/// * `gemini://example.com/app/` might be where an SCGI app is hosted
/// * `gemini://example.com/` might be some static landing page linking to both the
/// gemlog and the app
///
/// **Note:** If you are serving *very long* `text/gemini` files using `serve_dir`,
/// then you should avoid setting this to true. Additionally, if using this option,
/// do not try to rewrite your links using [`Request::rewrite_path`] or
/// [`Response::rewrite_all`], as this will apply the rewrite twice.
/// If the user sent a request to `/app/path` in this case, the app would see it as
/// `/path` automatically, so the app doesn't need to care if it's mounted on `/` or
/// `/app`, because it can handle any request to `/path` the same.
///
/// For more information about rewriting, see [`Request::rewrite_path`].
/// The problem comes when the app needs to write a link. If an app were to send a
/// link to `/path`, expecting the user to come back with a request to `/path`, it
/// might be surprised to see that the user never arrives, and the user might be
/// surprised to find a `51 Not Found` error page.
///
/// This happens because when the user clicks the link to `/path`, their client takes
/// them to `gemini://example.com/path`. The gemini server doesn't see any apps or
/// files being served on `/path`, so it sends a `NotFound`.
///
/// The app *should* have linked to `/app/path`, but in order to do that, it would
/// need to know that it was mounted at `/app`, and include a bunch of logic to figure
/// out the write path. Thankfully, kochab can take care of this for you.
///
/// There are three main tools at your disposal for link rewriting:
///
/// * [`Server::set_autorewrite()`] is the easiest tool to use, and the one that will
/// work the best for most people. By setting this option on your server, it will
/// automatcially check for any gemini links in it's response before it's sent, and
/// rewrite them to be appropriate relative to the app. In this case, our example
/// app would simply send the link as `/path`, and kochab would catch and rewrite it
/// before it's sent out. For more information about this method, keep reading this
/// method's docs.
/// * [`Response::rewrite_all()`] will attempt to rewrite any links it finds in a
/// single response. This is the method that underlies [`Server::set_autorewrite()`],
/// but by calling it on your responses manually, you can choose exactly what
/// responses are rewritten.
/// * [`Request::rewrite_path()`] will rewrite a single link. This method works best
/// for when you need a lot of precision, like including links that need to be
/// rewritten alongside links that don't, or when you're rewriting links in
/// responses that aren't `text/gemini`.
///
/// All of these methods work on both `scgi_srv` and `gemini_srv` modes, so you can
/// use them regardless of what you plan on compiling your server to, which is
/// recommended if you're planning to offer compilation to either, or if you would
/// like to be able to change later. It's worth noting that while it will *work*, on
/// `gemini_srv` mode, `gemini_srv` servers are *always* mounted at the base path, so
/// this method really won't do anything other than sign off that the link is good.
///
/// If there's a problem with rewriting the URLs, typically because the proxy
/// server/SCGI client being used doesn't correctly implement the SCGI spec, then any
/// `text/gemini` responses bearing an absolute link will be `40 TEMPORARY FAILURE`,
/// and an error will be logged explaining what went wrong.
///
/// For more information about how rewritten paths are calculated, see
/// [`Request::rewrite_path()`].\
/// For more information about what responses are rewritten,
/// see [`Response::rewrite_all()`].
pub fn set_autorewrite(mut self, autorewrite: bool) -> Self {
self.autorewrite = autorewrite;
self

View file

@ -222,8 +222,16 @@ impl Request {
/// 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)
/// * `SCRIPT_PATH` (Used by [mollybrown] and [stargazer])
/// * `SCRIPT_NAME` (Used by [GLV-1.12556])
///
/// [mollybrown]: https://tildegit.org/solderpunk/molly-brown
/// [stargazer]: https://git.sr.ht/~zethra/stargazer/
/// [GLV-1.12556]: https://github.com/spc476/GLV-1.12556
///
/// For an overview of methods for rewriting links, see [`Server::set_autorewrite()`].
///
/// [`Server::set_autorewrite()`]: crate::Server::set_autorewrite()
pub fn rewrite_path(&self, path: impl AsRef<str>) -> Option<String> {
#[cfg(feature = "scgi_srv")] {
self.script_path.as_ref().map(|base| {

View file

@ -148,9 +148,6 @@ impl Response {
#[cfg_attr(feature="gemini_srv",allow(unused_variables))]
/// Rewrite any links in this response based on the path identified by a request
///
/// For more information about what rewriting a link means, see
/// [`Request::rewrite_path`].
///
/// Currently, this rewrites any links in:
/// * SUCCESS (10) requests with a `text/gemini` MIME
/// * REDIRECT (3X) requests
@ -163,10 +160,18 @@ impl Response {
/// this process, this error will be raised
///
/// If the request does not contain enough information to rewrite a link (in other
/// words, if [`Requet::rewrite_path`] returns [`None`]), then false is returned. In
/// all other cases, this method returns true.
/// words, if [`Request::rewrite_path()`] returns [`None`]), then false is returned.
/// In all other cases, this method returns true.
///
/// Panics if a "text/gemini" response is not UTF-8 formatted
///
/// For an overview of methods for rewriting links, see
/// [`Server::set_autorewrite()`].\
/// For more information about how rewritten paths are calculated, see
/// [`Request::rewrite_path()`].
///
/// [`Server::set_autorewrite()`]: crate::Server::set_autorewrite()
/// [`Request::rewrite_path()`]: crate::Server::set_autorewrite()
pub async fn rewrite_all(&mut self, based_on: &crate::Request) -> std::io::Result<bool> {
#[cfg(feature = "scgi_srv")]
match self.status {