Mod_rewrite in two directions? - apache

An existing page is called /foo/bar.php. What I have done is a rewrite so that when a user types /foobar, it load the contents of /foo/bar.php (while keeping /foobar in the url bar)
But I also want the opposite - when a user clicks on a link or types /foo/bar.php, I want to have /foobar in the url. The reason is to avoid manually changing all the links.
How could I do that (if possible without an http redirect, but via some rewrite magic)? And is it possible for those two rules to co-exist?
Edit - After the first response, I realized my description of the problem was not proper. /foobar is not supposed to be a concatenation of foo, bar of /foo/bar.php, but an arbitrary string (/whatever).
Edit 2:
I now added RewriteRule ^whetever/?$ /foo/bar.php [L] in the / .htaccess. Then I added RewriteRule bar\.php$ /whetever [R=302,L] in the /foo .htaccess. The problem is it 's a circular reference and fails.
Thanks,
John

RewriteEngine On
RewriteCond %{REQUEST_URI} ^/foo/[^/]+\.php$
RewriteCond %{IS_SUBREQ} !true
RewriteRule ^/foo/([^/]+)\.php$ /foo$1 [R,L]
RewriteCond %{REQUEST_URI} ^/foo[^/]
RewriteRule ^/foo(.*) /foo/$1.php [L]
The first part matches /foo/something.php and transforms them into /foosomething, but only if it is not a sub-request.
The second part takes any /foosometing and transforms it into /foo/something.php, via sub-request

You can try matching against %{THE_REQUEST} and only do the redirect when the actual request is for the php file:
RewriteEngine On
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /foo/bar\.php
RewriteRule bar\.php$ /whatever [R=302,L]
RewriteRule ^whatever/?$ /foo/bar.php [L]

Related

.htaccess RewriteRule gives right link but also a 404

I'm hosting different sites
http://example.nl/example.nl/_sites/byos/
http://example.nl/example.nl/_sites/eggbot/
http://example.nl/example.nl/_sites/hslab/
http://example.nl/example.nl/_sites/prolactin/
And yes there is a folder that has the same name as the domain, there is a reason for that.
And I want the links to become:
http://example.nl/byos/
http://example.nl/eggbot/
http://example.nl/hslab/
http://example.nl/prolactin/
This is one of the many attempts:
RewriteEngine On
Options +FollowSymlinks
RewriteCond %{REQUEST_URI} !(.*)example.nl/_sites
RewriteRule ^(.*)$ example.nl/_sites/$1 [L]
And this one:
Options +FollowSymLinks -MultiViews
# Turn mod_rewrite on
RewriteEngine On
RewriteBase /
RewriteRule ^example.nl/_sites/(.*)$ /$1 [L,NC,R]
The last one brings me close, it changes the address in what I want it to be, but it also results in a 404 now.
I also tried it with renaming the example.nl folder so it is not the same as the domain name but the problem seems to be the same.
In case it is important for later, I also have folders with files here:
http://example.nl/example.nl/_misc/
http://example.nl/example.nl/_plugins/
But I don't care if those get renamed, since they won't appear in the url bar, unless the user goes directly to one of those files, but I don't care about that.
So how can I omit the example.nl/_sites/ part and still have the website working?
I have seen the similar questions on SO, but for me it looks like Chinese in another dialect.
---- edit:
using the following of the answer from anubhava:
RewriteCond %{HTTP_HOST}::%{THE_REQUEST} ^(?:www\.)?([^:]+)::GET\s/+\1/_sites/(\S*)\s [NC]
RewriteRule ^ /%2 [R=301,NE,L]
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$ [NC]
RewriteRule ^[^/]+/?$ %1/_sites%{REQUEST_URI} [L]
I don't get a 404 anymore.
But this files for example:
http://hslab.nl/hslab.nl/_misc/bna.js
It tries to load it as:
http://hslab.nl/_misc/bna.js
Which fails. In the code it was targeted as:
src="../../_misc/bna.js"
In case it helps here is a screenshot of the folder hslab.nl:
Without hardcoding host name, you may try these rules in your site root .htaccess:
RewriteCond %{HTTP_HOST}::%{THE_REQUEST} ^(?:www\.)?([^:]+)::GET\s/+\1/_sites/(\S*)\s [NC]
RewriteRule ^ /%2 [R=301,NE,L]
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$ [NC]
RewriteRule ^[^/]+/?$ %1/_sites%{REQUEST_URI} [L]
With your shown samples, could you please try following. Fair warning I have written this in mobile so yet to test it should work IMHO will test it in sometime too. Also since you mentioned there could be multiple domains so I have specifically put a condition to check if it's example.nl here in case you want to rewrite request for any domain then we could omit that condition too.
RewriteEngine ON
RewriteCond %{HTTP_HOST} ^example\.nl$ [NC]
RewriteRule ^([a-zA-Z]+)/?$ %{HTTP_HOST}/_sites/$1 [L]
Note: in case you directories/folders are not necessarily starting with alphabets and could be anything then change regex in above from ^([a-zA-Z]+)/?$ TO ^([.*])/?$

Htaccess rules get overriden

I want my .htaccess in the web server's root dir to redirect any request starting with ^assets/(.*)$ to the folder public/$1. All other requests have to go to index.php?request=$1. I also want to keep get parameters (L flag does it) in this case.
RewriteEngine on
RewriteBase /
RewriteRule ^assets/(.*)$ public/$1 [QSA,L]
RewriteRule ^(?!assets)(.*)$ index.php?request=$1 [L,QSA]
The only problem is that the last line overrides the previous :/
I also tested with (.*) but without success.
Thanks for your help.
Try this:
RewriteEngine on
RewriteRule "^/assets/(.*)$" "/public/$1" [L,QSA]
RewriteCond %{REQUEST_URI} "!^/assets/"
RewriteCond %{REQUEST_URI} "!^/index.php"
RewriteCond %{REQUEST_URI} "!^/public"
RewriteRule (.*) "/index.php?request=$1" [L,QSA]
QSA: appends the parameters to the rewritten part
L: last. Which means if it matches, do not process any other rewrite.
Rewrites start at /
To apply a condition on a RewriteRule, use RewriteCond
References:
https://httpd.apache.org/docs/2.4/rewrite/flags.html
https://httpd.apache.org/docs/current/mod/mod_rewrite.html
The first rule says:
if it starts with "/assets/", anything following the second / will be rewritten as "/public/$1".
The RewriteCond and RewriteRule says:
if it does not start by "/assets/", take whatever you received, add it at the end of "/index.php?request=".
So http://www.example.com/directory/somepage.html will go to http://www.example.com/index.php?request=/directory/somepage.html.
If there are parameters in the request, they are appended at the end like so:
http://www.example.com/directory/somepage.html?a=1&b=4 will go to
http://www.example.com/index.php?request=/directory/somepage.html?a=1&b=4
EDIT Nov 19 1115
Added a second RewriteCond to make sure "/index.php" does not rewrite to itself. And a third, in case you want "/public" to also not redirect to "/index.php".

mod_rewrite configuration does not work

I have a page with urls like this:
http://example.com/index.php?site=contact
http://example.com/index.php?site=about
So I try to create custom urls like
http://example.com/contact-the-person
http://example.com/cityname/about
to avoid duplicate content the first url need a permanent redirect into the new code.
this is my code:
RewriteEngine On
RewriteBase /
RewriteCond %{THE_REQUEST} \s/+index\.php?site=contact[\s?] [NC]
RewriteRule ^/contact-the-person [R=301,L]
RewriteRule ^contact-the-person/?$ index.php?site=contact [L,NC]
Update:
I changed my code into
RewriteEngine on
RewriteRule ^cityname/about$ index.php?site=contact
and it works now. I can open the url with both links
http://example.com/index.php?site=contact
http://example.com/cityname/about
I just need a redirect from the php version to the clean url now, to avoid dublicate content
Get rid of RewriteBase, if your base is / it is redundant and just complicates things. I am not sure what your RewriteCond is doing, but it isn't necessary to do the 2 rewrites you describe in the question, so get rid of it too.
To make /contact-the-person work:
RewriteRule ^/contact-the-person index.php?site=contact [L,NC]
To make /cityname/about work:
RewriteRule ^/cityname/about index.php?site=about [L,NC]
So the complete file:
RewriteEngine On
RewriteRule ^/contact-the-person /index.php?site=contact [L,NC]
RewriteRule ^/cityname/about /index.php?site=about [L,NC]
UPDATE
To also redirect your index.php?site=contact links to the new pretty format, you'll need to do an external redirect, so that the browser actually makes a new request, and the URL in the browser changes. Do that by adding R to the flags. 301 specifies the http response header, and will ensure your link rankings are preserved. For the example you gave, add a new rule:
RewriteRule ^/index.php?site=contact /contact-the-person [L,R=301]

How to use htaccess Rewrite rule for just part of a url

I am trying to create a rewrite rule in my httacess file for part of the url. I want to rewrite the url if the request contains a specific string. For example change the url only if contains /members/
So
mydomain.com/members/
mydomain.com/members/activity/ros1...
mydomain.com/members/ay/bd...
ALL above should change to another url because matches /members/ string in the url
RewriteEngine on
RewriteCond %{THE_REQUEST} ^GET /members/(.*)
RewriteRule ^(.*)$ - [F,L]
RewriteEngine on
RewriteCond %{REQUEST_URI} ^/members(.*)
RewriteRule ^(.*)$ - [F,L]
I have tried various combinations but does not seem to work. I'm sure I'm doing something really wrong as not on expert on this. Appreciate any pointers.
RewriteCond %{REQUEST_URI} ^/members
RewriteRule ^(.*)$ http://www.google.com/$1 [R, 301]
Would be something i would try to redirect a request for /members and send them to another domain. (with the same request uri). Further info on mod_rewrite can be found https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html#rewriterule
You are using the F flag in your rewrites. The flag is to send the Forbidden status back to client. If you want to redirect the user to another URL, you'll need to pass that URL as the second parameter to RewriteRule directive with the R flag:
RewriteEngine On
RewriteRule ^members\b http://some-other-website.com [R]

Apache mod_rewrite going berserk - redirecting where it shouldn't

I have a script that echoes a meta redirect to a page called account_management.php5, but for some reason it automatically redirects from there to index.php5. My .htaccess file handles a couple of redirects automatically, for example index.html|php5 to the domain root, and that's the only place I can see this problem originating, but I don't understand why. This is my .htaccess file:
RewriteEngine On
#remember to change this to aromaclear
RewriteCond %{HTTP_HOST} !^sinaesthesia\.co.uk$ [NC]
RewriteRule ^(.*)$ http://sinaesthesia.co.uk/$1 [R=301,L]
RewriteCond %{THE_REQUEST} ^GET\ .*/index\.(php5|html)\ HTTP
RewriteRule ^(.*)index\.(php5|html)$ /$1 [R=301,L]
#translate any .html ending into .php5
RewriteRule ^(.*)\.html$ /$1\.php5
#change / for ?
RewriteRule ^(.*)\.html/(.*)$ /$1\.html?$2
#strip .html from search res page
RewriteRule ^(.*)search/(.*)$ /$1search_results\.html/search=$2
#translate product details link from search res page
RewriteRule ^products/(.*)/(.*)/(.*)$ /product_details.php5?category=$1&title=$2&id=$3 [L]
#Translate products/psorisis/chamomile-skin-cream-P[x] to productview.php5?id=1
RewriteRule ^products/.*-P([0-9]+) /productview.php5?id=$1 [L]
Wrong:
RewriteRule ^(.*)\.html$ /$1\.php5
Right:
RewriteRule ^(.*)\.html$ /$1.php5
Righter:
RewriteRule ^(.*)\.html$ /$1.php5 [QSA]
This same mistake of escaping special chars in the second param of RewriteRule is happening in other rules too, I don't know if apache will handle it, but I know you don't need it because second param is not a regexp.
Never compare to %{THE_REQUEST}, thats a weird thing to do, you don't need that. Moreover, this condition is fine without it. Just put there:
RewriteRule ^(.*)index\.(php5|html)$ $1 [R=301,QSA,L]
Now look at it:
RewriteRule ^(.*)\.html/(.*)$ /$1.html?$2
First, you are still accepting that there are references to .html files, just after trying to translate all .html to .php5, there's something wrong here.
Moreover, you are defineing as QueryString something that was originally a file path, and are not even putting it in a key. It won't work, it need some more treatment.
#strip .html from search res page
RewriteRule ^(.*)search/(.*)$ /$1search_results.html/search=$2
Wasn't it supposed to strip the .html? Because it is actually putting a .html there. Maybe as it is not an [L] it get fixed in the next loop, but you could just get all fixed right here.
#translate product details link from search res page
RewriteRule ^products/(.*)/(.*)/(.*)$ /product_details.php5?category=$1&title=$2&id=$3 [L]
This one full of .* is potentially unstable, specially delimitating the end. You should do this:
RewriteRule ^products/([^/]*)/([^/]*)/([^/]*) /product_details.php5?category=$1&title=$2&id=$3 [L]
# or:
RewriteRule ^products/(.*?)/(.*?)/([^/]*) /product_details.php5?category=$1&title=$2&id=$3 [L]
The last one looks correct, except that you should strip the special character that may be faced as a range delimiter, the "-". I don't think it work after a *, but just to be sure and correct the syntax:
RewriteRule ^products/.*\-P([0-9]+) /productview.php5?id=$1 [L]
Add this just after RewriteEngine on
RewriteLogLevel 9
RewriteLog /tmp/rw.log
Then restart the webserver. It should help you debug the problem.
Edit: Sorry, I didn't notice the .htaccess above. This will only work from the main apache configuration file.