HTACCESS - Get Path without filename - .htaccess

I was wondering how to get just the request path without the file name, i.e. the folder where the requested file is in. Is that possible with the HTACCESS file or is there a variable like% {REQUEST_URI} without the filename?
I would then like to deposit the code in the htaccess in the / directory. I want to find out the folder path so that I don't have to enter the path for each subfolder individually. So when I access example.com/folder the code checks the same as it does on example.com/folder2.
So I want to redirect TO a maintenance page FROM every URL in whose same folder there is a maintenance.txt.
I would then like to check with an If statement in the folder of the requested file whether a certain file ("maintenance.txt") exists. Because I want to "block" every folder where this file exists in it.
Maybe it is possible with RegEx? I thought of something like this:
<If "-f %{FOLDER_OF_REQUESTED_FILE}/maintenance.txt">
ErrorDocument 200 /assets/maintenance.html
</If>

Related

Is it possible to wildcard a filename string to password protect a file with htaccess?

Example: wp_file*.log -- what that should do is to password protect every file whose filename start with wp_file and ends with .log -- for example wp_file-22.log and wp_file_randomfile.log.
Possible?
The way I would make this, is by adding a rewrite rule for those files, redirect to some PHP file with the origional request in the GET. The PHP file can than show a password box and eventually the content of the log file once logged in.
RewriteEngine On
RewriteRule wp_file(.*)\.log /somePHPfile.php?logFile=wp_file$1 [L]
(not tested)
If you dont need access to the log files via your website (but use e.g. ftp), than you can rewrite the requests to those files to another page
RewriteEngine On
RewriteRule wp_file(.*)\.log /index.php [L]

Canonical Header Links for PDF and Image files in .htaccess

I'm attempting to setup Canonical links for a number of PDF and images files on my website.
Example Folder Structure:
/index.php
/docs/
file.pdf
/folder1/
file.pdf
/folder2/
file1.pdf
file2.pdf
/img/
sprite.png
/slideshow/
slide1.jpg
slide2.jpg
Example PDF URL to Canonical URL:
http://www.example.com/docs/folder1/file.pdf --> http://www.example.com/products/folder1/
I am trying to avoid having to put individual .htaccess files in each of the sub-folders that contain all of my images and PDFs. I currently have 7 "main" folders, and each of these folders have any where from 2-10 sub-folders, and most sub-folders have their own sub-folders. I have roughly 80 PDFs, and even more images.
I'm looking for a (semi)dynamic solution where all files in a certain folder will have the Canonical Link set to a single url. I want to keep as much as possible in a single .htaccess file.
I know that <Files> and <FilesMatch> do not understand paths, and that <Directory> and <DirectoryMatch> don't work in .htaccess files.
Is there a fairly simple way to accomplish this?
I don't know of a way to solve this with apache rules alone as it would require some sort of regex matching and reusing the result of the match in a directive, which isn't possible.
However, it's pretty simple if you introduce a php script into the mix:
RewriteEngine On
RewriteCond %{REQUEST_URI} \.(jpg|png|pdf)$
RewriteRule (.*) /canonical-header.php?path=$1
Note that this would send requests for all jpg, png and pdf files to the script regardless of the folder name. If you want to include only specific folders, you could add another RewriteCond to accomplish that.
Now the canonical-header.php script:
<?php
// Checking for the presence of the path variable in the query string allows us to easily 404 any requests that
// come directly to this script, just to be safe.
if (!empty($_GET['path'])) {
// Be sure to add any new file types you want to handle here so the correct content-type header will be sent.
$mimeTypes = array(
'pdf' => 'application/pdf',
'jpg' => 'image/jpeg',
'png' => 'image/png',
);
$path = filter_input(INPUT_GET, 'path', FILTER_SANITIZE_URL);
$file = realpath($path);
$extension = pathinfo($path, PATHINFO_EXTENSION);
$canonicalUrl = 'http://' . $_SERVER['HTTP_HOST'] . '/' . dirname($path);
$type = $mimeTypes[$extension];
// Verify that the file exists and is readable, or send 404
if (is_readable($file)) {
header('Content-Type: ' . $type);
header('Link <' . $canonicalUrl . '>; rel="canonical"');
readfile(realpath($path));
} else {
header('HTTP/1.0 404 Not Found');
echo "File not found";
}
} else {
header('HTTP/1.0 404 Not Found');
echo "File not found";
}
Please consider this code untested and check that it works as expected across browsers before releasing it to production.
I was able to achieve adding canonical links for files in different directories through a single .htacess file.
The following code adds a canonical link for each file pointing to the same directory:
<FilesMatch "\.(jpg|png|pdf)$">
RewriteRule ([^/]+)\.(jpg|png|pdf)$ - [E=FILENAME:%{HTTP_HOST}/<your-desired-location>/$1.$2]
Header add Link '<https://%{FILENAME}e>; rel="canonical"'
</FilesMatch>
And the code below adds a canonical link to the file's requested URL, which in many cases will be its actual location on the server:
<FilesMatch "\.(jpg|png|pdf)$">
RewriteRule ([^/]+)\.(jpg|png|pdf)$ - [E=FILENAME:%{HTTP_HOST}%{REQUEST_URI}]
Header set Link '<https://%{FILENAME}e>; rel="canonical"'
</FilesMatch>
Here is the solution !!!
you can use .htacess file for controlling header which is more simple way to manage headers.
How you can do ?
Lets take a example, I have a pdf named "testPDF.pdf" which is in the root folder of my site.
All you have to do, pasted following code into .htaccss file.
<Files testPDF.pdf >
Header add Link '<http://<your_site_name>.com/ >; rel="canonical"'
</Files>
Once you've added that to your .htaccess file, you'll need to test your header to ensure that it's working accurately
For an IIS solution, try something like this.
Response.AppendHeader("Link", "<" + "https://" + Request.Url.Host + "/" + product.GetSeName() + ">; rel=\"canonical\"");
this was added to a function which generated a PDF version of the webpage :)

Is it possible to remove a "folder" at the end of a URL using an .htaccess file?

so I have a bunch of URLs
http://foo.com/people/smith/john/1
http://foo.com/people/cartman/eric/2
http://foo.com/people/simpson/bart/3
I want to change the URLs like so
http://foo.com/people/smith/john/
http://foo.com/people/cartman/eric/
http://foo.com/people/simpson/bart/
So basically, I think I need to write a condition that looks for the folder 'people' and removes the third directory from the URL. Is this possible with my .htaccess?
In the htaccess file in your document root, try:
RewriteEngine On
RewriteRule ^people/([^/]+)/([^/]+)/.+ /people/$1/$2 [L,R=301]
This redirects the browser (changing the URL in the address bar) from
http://foo.com/people/smith/john/1
to
http://foo.com/people/smith/john/
If you don't want the URL in the browser's address bar to change, remove the ,R=301 from the square brackets.

htaccess to redirect both folder and file name

I have a file in a folder like this folder1/folder2/folder3/filename.htm. I also have another file like this folder1/folder2/folder3-filename.htm. When i browse the url mysite.com/folder1/folder2/folder3/filename.htm, i want the folder3-filename.htm will be served (displayed)
I know some basics about file name rewrite rules, but i have not seen any mixed-up combination of folder name and file name in that way.
Could anyone help me how to do it?
Using the expression [^/]+ to match all characters up to but not including the the next / and then .+ to match everything after the last /, the following will work:
RewriteEngine On
RewriteRule ^folder1/folder2/([^/]+)/(.+)$ folder1/folder2/$1-$2 [L]

htaccess - creating directories and files of the same name

I want to create a bunch of files without an extension showing at the end. The easiest way to do that was to do this:
/usa/index.php
/usa/alaska/index.php
/usa/alabama/index.php
/usa/california/index.php
What I want to do is this
/usa/alaska.php
/usa/alabama.php
/usa/california.php
and have it show up as:
/usa/alaska
/usa/alabama
/usa/california
However, I have one more level I want to add to this, the cities
/usa/alaska/adak.php
/usa/alaska/anchorage.php
/usa/california/los-angles.php
I don't want the ".php" showing up, but then each state exists as both a file and a directory. What I want is an htaccess rule that serves up the file version of the file, not the directory which is the default. I also want to strip the .php off of the end of the files so the final result looks like
/usa
/usa/alaska (alaska.php)
/usa/alaska/adak (adak.php)
I know I can get close to this by creating all the directories and using index.php for each directory, but then I will have thousands of directories each with one file in it and updating is a pain in the butt. I would much rather have one directory with 1000 files in it, than 1000 directories with 1 file in it.
Please, can someone point me in the right direction and know that I am doing this for all 50 states.
Jim
I would also suggest using a single php (e.g. index.php) file and redirecting all urls starting with usa to it, instead of separating them in different directories and files. The you'd need a couple of rewrite rules like the following
RewriteEngine On
RewriteRule ^usa/([^/.]+)$ index.php?state=$1 [L]
RewriteRule ^usa/([^/]+)/([^/.]+)$ index.php?state=$1&city=$2 [L]
So then in your index.php you'd only need to check the $_GET parameters.
Update:
If you don't feel comfortable enough to use a database and pull the needed data from there you could always use the parameters to dynamically include/require the needed files. Something like this
<?php
$source = ''; //or the 'ROOT' directory
if(isset($_GET['state'])) $source .= $_GET['state'].'/';
if(isset($_GET['city'])) $source .= $_GET['city'].'.php';
include($source); // here $source would be something like 'alaska/adak.php'
// and is assumed that the dir 'alaska' is on the same
// level as 'index.php'
?>
But to answer your original question nevertheless you could use the following .htaccess
RewriteEngine On
RewriteRule ^usa/([^/.]+)$ usa/$1.php [L]
RewriteRule ^usa/([^/]+)/([^/.]+)$ usa/$1/$2.php [L]
what about creating just one single file:
/usa/index.php
With
$_SERVER["REQUEST_URI"]
you can read the current URI.
Well, now if a user enters "http://domain.foo/usa/alaska" for example, he will get an 404 error of course.
But to call your index.php instead, you could write this line to the .htaccess:
ErrorDocument 404 /usa/index.php
Now the index.php receives everything what is written to the URI and you can match the result and include files or handle errors.
But maybe there is a better solution with .htaccess only, don't know. :)

Resources