Convert path to querystring and preserve initial querystring parameters - .htaccess

I have an incoming path like this
http://acme.com/product/xxxxxx?utm_campaign=yyyyy
I need to convert this to
$http://acme.com/product?id=xxxxx&utm_campaign=yyyyy
The number of parameters are arbitrary, so there may be 1, none or 10.
I have these .htaccess rules, which are close to working:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/?product/(.*?)/?$ /product?id=$1 [L,QSA]
The problem with this code is that the result ends up with two question marks. For instance:
http://acme.com/product/xxxxxx?utm_campaign=yyyyy
becomes
http://acme.com/product?id=xxxxxx?utm_campaign=yyyyy
instead of
http://acme.com/product?id=xxxxxx&utm_campaign=yyyyy

Related

Getting multiple variables with Mod Rewrite

This my .htaccess file:
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^products/([^/\.]+)/?$ /product.php?$1
RewriteRule ^category/([^/\.]+)/?$ /category.php?cat=$1&page=$2 [QSA,L]
the link i put into the browser is site.com/category/batteries/1/ where batteries is category and 1 would be the page. However, my site only gets the category (so site.com/category/batteries/ works, but site.com/category/batteries/1/ returns a 404.)
category.php gets the value being passed in cat, but not the value in page. I keep reading on this, but just can't understand where I'm going wrong.
You're missing a capturing group so $2 is never set. Try:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^products/(.*+)/?$ product.php?$1
RewriteRule ^category/(.*+)/(\d+)/?$ category.php?cat=$1&page=$2 [QSA,L]
Changing the regex worked. Just getting the text inbetween slashes instead of trying to find the digit gave me the desired result.
RewriteRule ^category/([^/]+)/([^/]+)/? /category.php?cat=$1&page=$2 [QSA,L]

htaccess with multiple levels

I saw htaccess guides here but i think im doing it wrong. Here's my sample code.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/$ page.php?p=$1&c=$2&gc=$3
The issue i am facing here is, there are 3 levels of page that have links to each level. I usually get "Not Found" if i am going to the first parameter, even the 2nd parameter. It shows correct only the 3rd parameter.
What i would like to know here is, how can i configure my htaccess to get the certain page without having the link ended-up to "Not Found".
Your rule only matches if the path contains 3 parts. You need to create 2 more rules for the case where the path contains 2 parts and where the path contains 1 part:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/([^/]+)/$ page.php?p=$1&c=$2 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/$ page.php?p=$1 [L]
I also advice to use the [L] flag on the rule you already have. This will speed up things a little bit and might also prevent weird behaviour, especially when you are using redirects.

Rewrite URL with .htaccess for multiple parameters

This question might be a duplicate. But I did not find any solution worked for me.
I want to rewrite URL, where I have one and two level parameters. first parameter is p and second is sp
www.domain.com/home should point to www.domain.com/index.php?p=home
and
www.domain.com/projects/99 should point to www.domain.com/index.php?p=projects&sp=99
How do I do in .htaccess?
Currently My htaccess is as followes,
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?p=$1
RewriteRule ^([^/]*)/([^/]*)\$ index.php?p=$1&sp=$2 [L]
The problem with this htaccess is that it correctly points one level url. ie., www.domain.com/home. But not the two level url. ie. www.domain.com/projects/99
You have to treat the rules separately. All Conditions preceding rules only apply to a single, immediately following rule. You tried to 'chain' two rules. The second rule never could have matched, since the first one was a catch-all that changed the syntax. Apart from that you have to make sure that the first rule does not catch unwanted requests. Also think about whether you want to use the * or the + operator in the patterns. I suggest you use the + operator, so that you have a clear error message when empty values are requested for a 'page' or a 'subpage'.
So this might come closer to what you are looking for:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)$ index.php?p=$1 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/([^/]+)$ index.php?p=$1&sp=$2 [L]

htaccess does not work rewrite rule

I've been struggling with my .htaccess file for weeks now, I changed it many times but it just won't work.
I have this in my .htaccess file:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^/([^./]+)\.html$ category.php?id=$1
RewriteRule ^/([^./]+)\.html$ tag.php?id=$1
RewriteRule ^/([^./]+)\.html$ play.php?id=$1
but it does not work.
Are you sure that mod_rewrite is turned on in Apache? Do you have access to httpd.conf? It would be better to do redirects there instead of with a .htaccess file.
Your conditions are only being applied to the first rule. Each set of RewriteCond's only get applied to the immediately following RewriteRule. So the conditions only get applied to RewriteRule ^/([^./]+)\.html$ category.php?id=$1 and the last 2 rules have no conditions at all.
Your conditions is to rewrite something that exists to something else, which will cause a rewrite loop. You probably wanted:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
Your 2nd and 3rd rules will never be applied because if someone requests /some-page.html the first rule's regex will match it and rewrite the URI to /category.php?id=some-page, then the next to rules will never match because the first rule already rewrote the URI to category.php.
Your regular expressions match a leading slash, URI's being applied in rewrite rules that are inside an htaccess file has the leading slash stripped out, so you want this instead:
RewriteRule ^([^./]+)\.html$ category.php?id=$1
1, 2 and 4 is easy. 3, not so much. You're going to have to figure out a unique way to represent an html page as a category, tag, or play. You can't have all 3 look identical, there's no way to tell which one you want. Take:
/something.html
Is that supposed to be a category? A tag? or a Play? Who knows, your rewrite rules surely don't. But if you preface each with a keyword, then you can differentiate:
/category/something.html
/tag/something.html
/play/something.html
And your rules would look like:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^category/([^./]+)\.html$ category.php?id=$1
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^tag/([^./]+)\.html$ tag.php?id=$1
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^play/([^./]+)\.html$ play.php?id=$1

Htaccess help, $1 being used before its set??? what?

I have this snippet
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond $1 !^(index\.php|images|img|css|js|robots\.txt)
RewriteRule (.*) index.php?/$1 [L]
It won't allow me to access a file at website.com/js/main.php
but it will let me access index.php
According to my webhost, $1 is being called before it is set. Any solutions?
I'll accept answers when i get back tomorrow. Thank you!
I'm assuming you want the rewrite to ignore the things which your condition currently specifies. In that case...
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond !^(index\.php|images|img|css|js|robots\.txt)
RewriteRule (.*) index.php?/$1 [L,QSA]
...should work fine. You'll probably want the QSA on there so that if there's a query string, it's properly handled.
Your web host is wrong. The order of ruleset processing is:
pattern in RewriteRule is tested (that will populate the $N references with values)
associated RewriteCond conditions are tested (if present)
Only if the pattern matches the current URL path and the associated condition is fulfilled, the pattern is applied.
So in your case the pattern (.*) is tested on the current URL path js/main.php (without local prefix /). It matches ($0=js/main.php, $1=js/main.php) so the three associated conditions are tested in the order they appear:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond $1 !^(index\.php|images|img|css|js|robots\.txt)
Assuming that the requested URL path /js/main.php does not refer to an existing file or directory, the first conditions are both true. But the third one will evaluate to false as $1=js/main.php and the pattern ^(index\.php|images|img|css|js|robots\.txt) matches (^js branch) js/main.php. So the condition is not fulfilled and the rule is not applied.

Resources