Remove trailing slashes from URLs

This commit is contained in:
Alex Cabal 2020-05-02 21:03:22 -05:00
parent cd74a155f4
commit 986183a83f
17 changed files with 71 additions and 48 deletions

View file

@ -81,6 +81,7 @@ Define domain standardebooks.org
SetEnvIf Request_URI "\.epub3$" logdownload
SetEnvIf Request_URI "\.azw3$" logdownload
CustomLog /var/log/local/downloads.log "%h [%{%Y-%m-%d %H:%M:%S %Z}t] \"%r\" %>s %b" env=logdownload
DirectorySlash Off
<Directory /standardebooks.org/web/www/>
# Disable .htaccess files
@ -162,11 +163,28 @@ Define domain standardebooks.org
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME}.xml -f
RewriteRule (.*) $1.xml [L]
# Remove trailing slashes
RewriteRule ^/(.+?)/$ /$1 [R=301,L]
# Redirect index pages
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} -d
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME}/index.php -f
RewriteRule (.*) /$1/index.php
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} -d
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME}/index.xml -f
RewriteRule (.*) /$1/index.xml
# Remove newline characters inserted by accident in some email clients
RewriteRule ^(.*)\r\n[\ ]?(.*)$ $1$2 [R=301,N]
RewriteRule ^(.*)/r/n[\ ]?(.*)$ $1$2 [R=301,N]
RewriteRule ^(.*)/[rn]$ $1 [R=301,N]
# Favicon rewrites
RewriteRule ^/(apple-touch|android-chrome|favicon|mstile|safari-pinned|browserconfig|manifest)([^/]+)$ /images/favicons/$1$2 [L]
# Redirect tools
RewriteRule ^/tools/?$ https://github.com/standardebooks/tools [R=302,L]
RewriteRule ^/tools$ https://github.com/standardebooks/tools [R=302,L]
# Redirect latest version of the manual
RewriteRule ^/manual/latest(.*) /manual/index.php?url=$1 [L]
@ -188,25 +206,18 @@ Define domain standardebooks.org
RewriteRule ^/ebooks/robert-louis-stevenson/treasure-island/milo-winter(.*?)$ /ebooks/robert-louis-stevenson/treasure-island$1 [R=301,L]
RewriteRule ^/ebooks/edgar-rice-burroughs/a-princess-of-mars/frank-e-schoonover(.*?)$ /ebooks/edgar-rice-burroughs/a-princess-of-mars$1 [R=301,L]
# Remove newline characters inserted by accident in some email clients
RewriteRule ^(.*)\r\n[\ ]?(.*)$ $1$2 [R=301,N]
RewriteRule ^(.*)/r/n[\ ]?(.*)$ $1$2 [R=301,N]
RewriteRule ^(.*)/[rn]$ $1 [R=301,N]
# Redirect cover images with caching sha's to the root image
# We do this because some sites like Google cache the cover image path, so changing it results in lots of 404s
RewriteRule ^/images/covers/(.+?)\-[a-z0-9]{8}\-(cover|hero)(@2x)?\.jpg$ /images/covers/$1-$2$3.jpg
# Force a trailing slash on author directories
RewriteRule ^/(tags|collections|ebooks)/([^\./]+?)$ /$1/$2/ [R=301,L]
RewriteRule ^/ebooks/([^\./]+?)/$ /ebooks/author.php?url-path=$1 [QSA]
RewriteRule ^/tags/([^\./]+?)/$ /ebooks/index.php?tag=$1 [QSA]
RewriteRule ^/collections/([^\./]+?)/$ /ebooks/index.php?collection=$1 [QSA]
RewriteRule ^/ebooks/([^\./]+?)$ /ebooks/author.php?url-path=$1 [QSA]
RewriteRule ^/tags/([^\./]+?)$ /ebooks/index.php?tag=$1 [QSA]
RewriteRule ^/collections/([^\./]+?)$ /ebooks/index.php?collection=$1 [QSA]
# Prevent this rule from firing if we're getting a distribution file
RewriteCond %{REQUEST_FILENAME} !^/ebooks/.+?/dist/.+$
RewriteCond %{REQUEST_FILENAME} !^/ebooks/.+?/src/.+$
RewriteRule ^/ebooks/([^\.]+?)/?$ /ebooks/ebook.php?url-path=$1
RewriteRule ^/ebooks/([^\.]+?)$ /ebooks/ebook.php?url-path=$1
</VirtualHost>
<VirtualHost *:80>

View file

@ -80,6 +80,7 @@ Define domain standardebooks.test
SetEnvIf Request_URI "\.epub3$" logdownload
SetEnvIf Request_URI "\.azw3$" logdownload
CustomLog /var/log/local/downloads.log "%h [%{%Y-%m-%d %H:%M:%S %Z}t] \"%r\" %>s %b" env=logdownload
DirectorySlash Off
<Directory /standardebooks.org/web/www/>
# Disable .htaccess files
@ -161,11 +162,28 @@ Define domain standardebooks.test
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME}.xml -f
RewriteRule (.*) $1.xml [L]
# Remove trailing slashes
RewriteRule ^/(.+?)/$ /$1 [R=301,L]
# Redirect index pages
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} -d
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME}/index.php -f
RewriteRule (.*) /$1/index.php
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} -d
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME}/index.xml -f
RewriteRule (.*) /$1/index.xml
# Remove newline characters inserted by accident in some email clients
RewriteRule ^(.*)\r\n[\ ]?(.*)$ $1$2 [R=301,N]
RewriteRule ^(.*)/r/n[\ ]?(.*)$ $1$2 [R=301,N]
RewriteRule ^(.*)/[rn]$ $1 [R=301,N]
# Favicon rewrites
RewriteRule ^/(apple-touch|android-chrome|favicon|mstile|safari-pinned|browserconfig|manifest)([^/]+)$ /images/favicons/$1$2 [L]
# Redirect tools
RewriteRule ^/tools/?$ https://github.com/standardebooks/tools [R=302,L]
RewriteRule ^/tools$ https://github.com/standardebooks/tools [R=302,L]
# Redirect latest version of the manual
RewriteRule ^/manual/latest(.*) /manual/index.php?url=$1 [L]
@ -182,27 +200,21 @@ Define domain standardebooks.test
RewriteRule ^/ebooks/nikolai-gogol/short-fiction/claud-field_isabel-f-hapgood_vizetelly-and-company/(.+?)$ /ebooks/nikolai-gogol/short-fiction/claud-field_isabel-f-hapgood_vizetelly-and-company_george-tolstoy/$1 [R=301,L]
RewriteRule ^/ebooks/h-g-wells/tales-of-space-and-time(.+)$ /ebooks/h-g-wells/short-fiction$1 [R=301,L]
RewriteRule ^/ebooks/omar-khayyam/the-rubaiyat-of-omar-khayyam/edward-fitzgerald/edmund-dulac(.*?)$ /ebooks/omar-khayyam/the-rubaiyat-of-omar-khayyam/edward-fitzgerald$1 [R=301,L]
RewriteRule ^/ebooks/alfred-lord-tennyson/idylls-of-the-king/gustave-dore(.*?)$ /ebooks/alfred-lord-tennyson/idylls-of-the-king$1 [R=301,L]
RewriteRule ^/ebooks/w-w-jacobs/the-lady-of-the-barge/maurice-greiffenhagen(.*?)$ /ebooks/w-w-jacobs/the-lady-of-the-barge$1 [R=301,L]
RewriteRule ^/ebooks/robert-louis-stevenson/treasure-island/milo-winter(.*?)$ /ebooks/robert-louis-stevenson/treasure-island$1 [R=301,L]
RewriteRule ^/ebooks/edgar-rice-burroughs/a-princess-of-mars/frank-e-schoonover(.*?)$ /ebooks/edgar-rice-burroughs/a-princess-of-mars$1 [R=301,L]
# Remove newline characters inserted by accident in some email clients
RewriteRule ^(.*)\r\n[\ ]?(.*)$ $1$2 [R=301,N]
RewriteRule ^(.*)/r/n[\ ]?(.*)$ $1$2 [R=301,N]
RewriteRule ^(.*)/[rn]$ $1 [R=301,N]
# Redirect cover images with caching sha's to the root image
# We do this because some sites like Google cache the cover image path, so changing it results in lots of 404s
RewriteRule ^/images/covers/(.+?)\-[a-z0-9]{8}\-(cover|hero)(@2x)?\.jpg$ /images/covers/$1-$2$3.jpg
# Force a trailing slash on author directories
RewriteRule ^/(tags|collections|ebooks)/([^\./]+?)$ /$1/$2/ [R=301,L]
RewriteRule ^/ebooks/([^\./]+?)/$ /ebooks/author.php?url-path=$1 [QSA]
RewriteRule ^/tags/([^\./]+?)/$ /ebooks/index.php?tag=$1 [QSA]
RewriteRule ^/collections/([^\./]+?)/$ /ebooks/index.php?collection=$1 [QSA]
RewriteRule ^/ebooks/([^\./]+?)$ /ebooks/author.php?url-path=$1 [QSA]
RewriteRule ^/tags/([^\./]+?)$ /ebooks/index.php?tag=$1 [QSA]
RewriteRule ^/collections/([^\./]+?)$ /ebooks/index.php?collection=$1 [QSA]
# Prevent this rule from firing if we're getting a distribution file
RewriteCond %{REQUEST_FILENAME} !^/ebooks/.+?/dist/.+$
RewriteCond %{REQUEST_FILENAME} !^/ebooks/.+?/src/.+$
RewriteRule ^/ebooks/([^\.]+?)/?$ /ebooks/ebook.php?url-path=$1
RewriteRule ^/ebooks/([^\.]+?)$ /ebooks/ebook.php?url-path=$1
</VirtualHost>

View file

@ -5,6 +5,6 @@ class Collection{
public function __construct(string $name){
$this->Name = $name;
$this->Url = '/collections/' . strtolower(str_replace(' ', '-', Formatter::ToPlainText(Formatter::RemoveDiacritics($this->Name)))) . '/';
$this->Url = '/collections/' . strtolower(str_replace(' ', '-', Formatter::ToPlainText(Formatter::RemoveDiacritics($this->Name))));
}
}

View file

@ -5,6 +5,6 @@ class Tag{
public function __construct(string $name){
$this->Name = $name;
$this->Url = '/tags/' . strtolower(str_replace(' ', '-', Formatter::ToPlainText($this->Name))) . '/';
$this->Url = '/tags/' . strtolower(str_replace(' ', '-', Formatter::ToPlainText($this->Name)));
}
}

View file

@ -11,7 +11,7 @@ print("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:schema="http://schema.org/">
<id><?= $webUrl ?>/opds/all</id>
<link href="<?= $webUrl ?>/opds/all" rel="self" type="application/atom+xml;profile=opds-catalog;kind=acquisition"/>
<link href="<?= $webUrl ?>/opds/" rel="start" type="application/atom+xml;profile=opds-catalog;kind=navigation"/>
<link href="<?= $webUrl ?>/opds" rel="start" type="application/atom+xml;profile=opds-catalog;kind=navigation"/>
<title>All Standard Ebooks</title>
<subtitle>Free and liberated ebooks, carefully produced for the true book lover.</subtitle>
<icon><?= $webUrl ?>/images/logo.png</icon>

View file

@ -1,5 +1,5 @@
<aside class="alert">
<p>Is there an out-of-copyright book youd like to read, but that we dont have in our catalog?</p>
<p><a href="/contribute/">Help us produce that ebook</a> so that others can read it in the future! Theres probably a basic transcription available at <a href="https://www.gutenberg.org">Project Gutenberg</a>&mdash;<a href="/contribute/">get in touch with us</a> and well help you make it meet Standard Ebooks standards.</p>
<p><a href="/contribute">Help us produce that ebook</a> so that others can read it in the future! Theres probably a basic transcription available at <a href="https://www.gutenberg.org">Project Gutenberg</a>&mdash;<a href="/contribute">get in touch with us</a> and well help you make it meet Standard Ebooks standards.</p>
<p>Any skill level, from simple proofreading to complete ebook production, is welcome. Were here to help!</p>
</aside>

View file

@ -1,19 +1,19 @@
<footer>
<ul>
<li>
<a href="/ebooks/">Ebooks</a>
<a href="/ebooks">Ebooks</a>
</li>
<li>
<a href="/about/">About</a>
<a href="/about">About</a>
</li>
<li>
<a href="/contribute/">Get Involved</a>
<a href="/contribute">Get Involved</a>
</li>
<li>
<a href="https://github.com/standardebooks">GitHub</a>
</li>
<li>
<a href="/opds/">OPDS</a>
<a href="/opds">OPDS</a>
</li>
<li>
<a href="/rss/new-releases">New Releases RSS Feed</a>

View file

@ -55,13 +55,13 @@ if(!isset($manual)){
<nav>
<ul>
<li>
<a<? if($highlight == 'ebooks'){ ?> class="highlighted"<? } ?> href="/ebooks/">Ebooks</a>
<a<? if($highlight == 'ebooks'){ ?> class="highlighted"<? } ?> href="/ebooks">Ebooks</a>
</li>
<li>
<a<? if($highlight == 'about'){ ?> class="highlighted"<? } ?> href="/about/">About</a>
<a<? if($highlight == 'about'){ ?> class="highlighted"<? } ?> href="/about">About</a>
</li>
<li>
<a<? if($highlight == 'contribute'){ ?> class="highlighted"<? } ?> href="/contribute/">Get Involved</a>
<a<? if($highlight == 'contribute'){ ?> class="highlighted"<? } ?> href="/contribute">Get Involved</a>
</li>
</ul>
</nav>

View file

@ -1,4 +1,4 @@
<form action="/ebooks/" method="get">
<form action="/ebooks" method="get">
<label class="search">
Search ebooks: <input type="search" name="query" placeholder="Search all ebooks..." value="<?= Formatter::ToPlainText($query ?? '') ?>" />
</label>

View file

@ -7,7 +7,7 @@ require_once('Core.php');
<p>This guide is meant to take you step-by-step through the creation of a complete Standard Ebook. While it might seem a little long, most of the text is a description of how to use various automated scripts. It can take just an hour or two for an experienced producer to produce a draft ebook for proofreading (depending on the complexity of the ebook, of course).</p>
<p>Our toolset is GNU/Linux-based, and producing an ebook from scratch currently requires working knowledge of the epub file format and of Unix-like systems like Mac or Linux.</p>
<p>Our toolset doesnt yet work natively on Windows, but there are <a href="https://www.howtogeek.com/170870/5-ways-to-run-linux-software-on-windows/">many ways to run Linux from within Windows</a>.</p>
<p>If you dont have this kind of technical expertise, you can still contribute! <a href="/contribute/">Check out our contributors page for details.</a></p>
<p>If you dont have this kind of technical expertise, you can still contribute! <a href="/contribute">Check out our contributors page for details.</a></p>
<ol class="full">
<li>
<h2>Set up the Standard Ebooks toolset and make sure its up-to-date</h2>

View file

@ -929,7 +929,7 @@ aside.sort a.button{
margin-left: 1rem;
}
form[action="/ebooks/"]{
form[action="/ebooks"]{
margin: 0 1rem;
}

View file

@ -25,8 +25,8 @@ try{
foreach(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($wwwFilesystemPath)) as $file){
// This iterator will do a deep scan on the directory. When we hit another directory, the filename will be "." and the path will contain the directory path.
// We want to find where the "src" directory is, and the directory directly below that will be the final web URL we're looking for.
if($file->getFilename() == '.' && preg_match('/\/src$/ius', $file->getPath())){
throw new SeeOtherEbookException(preg_replace(['|' . SITE_ROOT . '/www|ius', '|/src$|ius'], '', $file->getPath()));
if($file->getFilename() == '.' && preg_match('|/src$|ius', $file->getPath())){
throw new SeeOtherEbookException(preg_replace(['|' . SITE_ROOT . '/web/www|ius', '|/src$|ius'], '', $file->getPath()));
}
}
}
@ -180,7 +180,7 @@ catch(\Exception $ex){
<h2>Improve this ebook</h2>
<p>Anyone can contribute to make a Standard Ebook better for everyone!</p>
<p>To report typos, typography errors, or other corrections, see <a href="/contribute/report-errors">how to report errors</a>.</p>
<? if($ebook->GitHubUrl !== null){ ?><p>If youre comfortable with technology and want to contribute directly, check out <a href="<?= Formatter::ToPlainText($ebook->GitHubUrl) ?>">this ebooks GitHub repository</a> and our <a href="/contribute/">contributors section</a>.</p><? } ?>
<? if($ebook->GitHubUrl !== null){ ?><p>If youre comfortable with technology and want to contribute directly, check out <a href="<?= Formatter::ToPlainText($ebook->GitHubUrl) ?>">this ebooks GitHub repository</a> and our <a href="/contribute">contributors section</a>.</p><? } ?>
</section>
<aside id="more-ebooks">

View file

@ -94,7 +94,7 @@ catch(\Exception $ex){
<h1><?= $pageHeader ?></h1>
<?= Template::SearchForm(['query' => $query]) ?>
<? if(sizeof($ebooks) == 0){ ?>
<p class="no-results">No ebooks matched your search. You can try different search terms, or <a href="/ebooks/">browse all of our ebooks</a>.</p>
<p class="no-results">No ebooks matched your search. You can try different search terms, or <a href="/ebooks">browse all of our ebooks</a>.</p>
<? }else{ ?>
<?= Template::EbookGrid(['ebooks' => $ebooks]) ?>
<? } ?>

View file

@ -157,7 +157,7 @@ require_once('Core.php');
</li>
<li id="other">
<h3>Other Devices</h3>
<p>We need help collecting instructions for transferring files to other devices. If you have a non-Kindle device, <a href="/contribute/">get in touch and help write these instructions</a>!</p>
<p>We need help collecting instructions for transferring files to other devices. If you have a non-Kindle device, <a href="/contribute">get in touch and help write these instructions</a>!</p>
</li>
</ul>
</section>

View file

@ -6,7 +6,7 @@ require_once('Core.php');
<img alt="Ereaders with a Standard Ebook open." src="/images/devices.png">
<p>Standard Ebooks is a volunteer driven, not-for-profit project that produces new editions of public domain ebooks that are lovingly formatted, open source, and free.</p>
<p>Ebook projects like <a href="https://www.gutenberg.org">Project Gutenberg</a> transcribe ebooks and make them available for the widest number of reading devices. Standard Ebooks takes ebooks from sources like Project Gutenberg, formats and typesets them using a carefully designed and professional-grade style manual, fully proofreads and corrects them, and then builds them to create a new edition that takes advantage of state-of-the-art ereader and browser technology.</p>
<p>Standard Ebooks arent just a beautiful addition to your digital library—theyre a high quality standard to build your own ebooks on.</p><a class="button next" href="/ebooks/">Browse our library of free ebooks</a>
<p>Standard Ebooks arent just a beautiful addition to your digital library—theyre a high quality standard to build your own ebooks on.</p><a class="button next" href="/ebooks">Browse our library of free ebooks</a>
<section>
<h2>What makes Standard Ebooks different?</h2>
<section>

View file

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<id>https://standardebooks.org/opds/</id>
<link href="https://standardebooks.org/opds/" rel="self" type="application/atom+xml;profile=opds-catalog;kind=navigation"/>
<link href="https://standardebooks.org/opds/" rel="start" type="application/atom+xml;profile=opds-catalog;kind=navigation"/>
<id>https://standardebooks.org/opds</id>
<link href="https://standardebooks.org/opds" rel="self" type="application/atom+xml;profile=opds-catalog;kind=navigation"/>
<link href="https://standardebooks.org/opds" rel="start" type="application/atom+xml;profile=opds-catalog;kind=navigation"/>
<title>Standard Ebooks</title>
<subtitle>Free and liberated ebooks, carefully produced for the true book lover.</subtitle>
<updated>2015-05-22T04:02:12Z</updated>

View file

@ -14,7 +14,7 @@ require_once('Core.php');
<p>You may also be interested in our OPDS feed, which is designed for use with ebook libraries like Calibre:</p>
<ul>
<li>
<p><a href="/opds/">The Standard Ebooks OPDS feed</a></p>
<p><a href="/opds">The Standard Ebooks OPDS feed</a></p>
</li>
</ul>
</article>