htaccess block original file however allow rewrite - .htaccess

I have the following entries in my /.htaccess
RewriteEngine On
RewriteBase /
RewriteRule ^signin.php - [L,gone]
RewriteRule ^sign-in/?$ /signin.php [L]
What I am trying to achieve is to allow the user to access /sign-in but not the original file /signin.php
I saw this other question however when I tried to implement the answer I get gone error on both /sign-in and /signin.php.
Referenced Question:
Alias within htaccess, and block access to original file? (URL rewriting)
Thanks for any help.

To redirect any direct requests for /signin.php to /sign-in and internally rewrite /sign-in back to /signin.php then you can do it like this:
RewriteEngine On
RewriteRule ^signin\.php$ /sign-in [R=301,L]
RewriteRule ^sign-in$ signin.php [END]
The END flag (Apache 2.4) prevents any further loops by the rewrite engine, so prevents the rewritten URL being redirected back to /sign-in, which would otherwise cause a redirect loop.
The END flag is not required on the first rule, since an external redirect will trigger immediately. (The L flag is still required.)
You do not need the RewriteBase directive here.
I removed the optional trailing slash on /sign-in as this potentially creates a duplicate content issue. If you wish to allow an optional trailing slash then redirect to the canonical URL (without the trailing slash, or with if you prefer) instead.
UPDATE:
I saw this other question however when I tried to implement the answer I get gone error on both /sign-in and /signin.php.
Referenced Question:
Alias within htaccess, and block access to original file? (URL rewriting)
The Apache solution in the referenced answer is not quite correct. The answer would seem to have been "accepted" for the first part regarding doing this in PHP instead.
At the time of that question (2011), they would have been using Apache 2.2. The END flag was only introduced in Apache 2.4.
They would have needed to have done it like this, to prevent a redirect loop:
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^about.php /about [L,R=301]
RewriteRule ^about$ about.php [L]

Related

.htaccess folder as parameter to root index.php

What I need is any subfolder to be passed as a parameter to the root index.php
This is the code and it actually works.
RewriteEngine On
RewriteBase /
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{SCRIPT_FILENAME} -d
RewriteRule ^(.+?)(/[^/]*|)$ index.php?dir=$1/ [L,QSA]
There is a problem:
When the url is like this (no end slash after 'projects'):
http://example.com/projects
the rewrite rule changes the link in the address bar and it looks like this:
http://example.com/projects/?dir=projects/
Is there a chance the url in the address bar always stays the same(no matter if there is an end slash or not) so the dir parameter is not visible to the user?
I tried with multiple rules - the first one to add an end slash, and then the second rule to pass the directory as parameter, but with no luck so far.
EDIT: so far thanks to w3d I managed to get it working. In the .htaccess just add:
DirectorySlash Off
tl;dr Make the trailing slash mandatory in the RewriteRule pattern (and remove the DirectorySlash Off directive, ie. keep it On).
RewriteRule ^(.+)/$ index.php?dir=$1/ [L,QSA]
As suggested in comments, this "strange" redirect is the result of mod_dir's DirectorySlash On directive, which is On by default. This can be quickly resolved by including DirectorySlash Off at the top of your .htaccess file (or making the trailing slash mandatory - see above and below).
The DirectorySlash On directive instructs Apache to automatically append a slash to URLs that end in a file system directory. In this sense it is "fixing" the URL. mod_dir achieves this with a 301 external redirect.
So, what is actually happening in the above, when DirectorySlash is enabled, is:
Initial request:
/projects (no trailing slash)
Internal rewrite in .htaccess:
/index.php?dir=projects/ (note that the request URL is still /projects)
mod_dir now kicks in and "fixes" the initial request (/projects --> /projects/) by appending a slash to the end of the URL-path. However, the query string from the rewritten URL (above) is passed through:
/projects/?dir=projects/ (this is a 301 external redirect, ie. a new request!)
Internal rewrite in .htaccess (again - new request):
/index.php?dir=projects/&dir=projects/ (note that the request is still /projects/?dir=projects/)
The doubling of the dir=projects/ query param is a result of the QSA flag on the RewriteRule (which I assume is required for other requests?). Your PHP script simply sees a single dir GET param (the later overwrites the former), unless you included dir[]=$1/ in your RewriteRule and you will end up with a 2-element array!
Your RewriteRule pattern also looks unnecessarily complex. You could simply make the trailing slash optional. ie:
RewriteRule ^(.+?)/?$ index.php?dir=$1/ [L,QSA]
Alternatively, having said all the above, you should probably leave DirectorySlash On (default) and simply make the trailing slash mandatory! For example:
RewriteRule ^(.+)/$ index.php?dir=$1/ [L,QSA]
mod_dir will now kick in before your internal rewrite (since it won't match without a trailing slash). This is also better for canonicalising your URLs and there are also potential security risks with turning it off.
Reference:
http://httpd.apache.org/docs/2.2/mod/mod_dir.html#directoryslash

Redirecting URLs with multiple parameters to clean URLs in .htaccess

I'm attempting to redirect URLs in .htaccess that have multiple parameters for example:
http://www.example.com/index.php?p=product&id=10&parent=0
to a clean URL on another domain like
http://example2.com/product/product10/
I believe my normal method of redirection (using a PHP header in an index file of a directory I've created) will not work due to not being able to put ? in a directory name.
I've done some minor .htaccess but have no experience with escaping parameters or anything and the only tutorials I can find are for escaping only a single parameter.
Can anybody give me a few pointers please?
You can use that in your root .htaccess:
RewriteEngine on
RewriteCond %{QUERY_STRING} ^p=([^&]+)&id=([^&]+) [NC]
RewriteRule ^index\.php$ http://example2.com/%1/%1%2/? [R=302]
Change [R=302] for [R=301] when test work well.

prefix a friendly url using mod rewrite in htaccess

Is it possible to prefix a htaccess rewrite rule
for example can a variable be used as a prefix to a url
website.com/$variable-for-sale/
/cupcakes-for-sale/
/pies-for-sale/
/flans-for-sale/
The idea is to then use that variable to display all the cupcakes/pies/flans for sale
How would this be written as a rewrite rule? Is it even possible?
Thanks
The first rule will take care of redirecting your ugly URL to Friendly like one.
The second rule will internally redirect it back so the browser URL remains the friendly URL while service the content of your page.
Options +FollowSymLinks -MultiViews
RewriteEngine On
RewriteBase /
# Redirect /?cake=anything to /anything-for-sale/
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s/+\?cake=([^&\s]+) [NC]
RewriteRule ^ /%1-for-sale/? [R=302,L]
# Internally forward /anything-for-sale/ to /?cake=anything
RewriteRule ^([^-]+)-for-sale/?$ /?cake=$1 [NC,L]
Keep in mind I am using R=302 its always better to use 302 which means temporary redirect while testing a new rule before making it permanent as the permanent will cache the information to your browser. Once the rule is confirmed to be working as expected change R=302 to R=301.
To extract variable, you need to use regex parentheses in the correct pattern, then you can use $1 to fetch the group:
RewriteRule ^([^-]+)-for-sale/$ /target.php?variable=$1 [L]
The "target" part is the script you use to display the "variable". Since your question doesn't mention what that is, you have to figure it out.

trouble with simple mod_rewrite redirect rule

I have mod_rewrite working in a development environment.
This testing domain is using these rules in an .htaccess file:
Options +FollowSymLinks
Options +Indexes
RewriteEngine on
# deal with potential pre-rewrite spidered / bookmarked urls
RewriteRule ^clothes/index.php?pg=([0-9]+)$ /clothes/index$1.php [R=301,L]
# deal with actual urls
RewriteRule ^clothes/[0-9a-z-]+-pr([0-9]+).php$ /clothes/product.php?pid=$1 [L]
The 2nd Rule works fine. Entering http ://testdomain.dev/clothes/shirt-pr32.php is silently delivered content from http ://testdomain.dev/clothes/product.php?pid=32 ...which is as desired and expected!
However, assuming this was applied to a live site, one that had originally used paths such as: http ://testdomain.dev/clothes/product.php?pid=32, I'd like to redirect any incoming requests following the old pattern to the new urls ...which is what the 1st Rule was intended to do.
My problem is my testing server seems to ignore the 1st Rule and serves the page as requested (page loads but address bar remains at http ://testdomain.dev/clothes/product.php?pid=32)
Any assistance or enlightenment would be most graciously accepted!
You need to match the query string within a RewriteCond, then backreference that RewriteCond from the rule. The RewriteRule only matches against the path, not the query string.
Here's a related post I previously answered with a similar request: Mod_rewrite rewrite example.com/page.php?v1=abc&v2=def to example.com/abc/def
You can't match against the query string in a rewrite rule, you need to use the `%{QUERY_STRING} variable in a condition and use the % to backrefernce groupings. So instead of:
RewriteRule ^clothes/index.php?pg=([0-9]+)$ /clothes/index$1.php [R=301,L]
You'll need:
RewriteCond %{QUERY_STRING} ^pg=([0-9]+)
RewriteRule ^clothes/index.php$ /clothes/index%1.php? [R=301,L]

My url rewrite redirects to mydomain.com/var/www/clients/client3/web25/

I'm trying to make a rewrite of a url on my joomla site. I have an extra page in there wiht some other stuff on it.
I have:
RewriteRule ^company/([^/]+) company?alias=$1 [NC]
where i want company/somecompany to show what the url company?alias=somecompany will give (not forward to it).
What i get instead is a redirection to:
http://www.mydomain.dk/var/www/clients/client2/web5/web/company?alias=somecompany
Also if i include a "-" like "company/some-company" it skips my rewrite and just goes to the joomla rewrite rules (and can't find the article)
What am I doing wrong?
You need to add a RewriteBase. When your rewrite rule's target doesn't start with a leading slash (making it an absolute URI), apache needs to guess whether it's a URI-path or a file-path, and it is incorrectly guessing that it's a file-path. Adding a base tells apache that it's a URI path.
RewriteBase /
or add a leading slash to your target: /company/?alias=$1
You also want to add a trailing slash to company and use the [L] flag:
RewriteRule ^company/([^/]+) company/?alias=$1 [L,NC]
The missing trailing slash may be the culprit that's causing mod_dir and DirectorySlash redirecting. And the L flag may be why the joomla rules are eventually getting applied.
Here is the working example:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /
RewriteRule ^/?old-folder/(.*)$ /new-folder/$1 [R=301,L]
</IfModule>
For more examples, check:
Learn Apache mod_rewrite: 13 Real-world Examples
Apache Conf Snippets for VS Code

Resources