.htaccess rewriterule not working - php

I have created a .htaccess rewiterule, but it is not doing anything.
The rule is :
RewriteEngine On
RewriteRule ^([^/]*)/([^/]*)\.html$ /showproduct.php?get-uid=$1&prod=$2 [L]
What I want to happen is that the following URL:
http://naturesgifts.co.nz/showproduct.php?get-uid=8&prod=whitesagespray
Changes to:
http://naturesgifts.co.nz/8/whitesagespray.html
However no redirect happens.
Please help.

RewriteCond %{QUERY_STRING} get-uid=([^&]+)&prod=([^&]+)
RewriteRule ^showproduct.php$ /%1/%2.html? [R=301,L]
Line 1: check if the query string contains the param get-uid and the param prod, [^&] matches any characters except & character
Line 2: if the request uri matches to showproduct.php exactly, redirect to /%1/%2.html permanently. %1 is the backreference to the first capture group ([^&]) whereas %2 matches the second capture group. [R=301] flag makes it redirect permanently.

Related

htaccess infinite loop issue

I have run into an issue with my .htaccess file.
The file changes the ugly URL such as http://localhost/news.php?article_slug=example-1 to http://localhost/news/example-1
This works perfectly, but when I go to http://localhost/news i get a 404 error.
Within news.php I have a redirect; so if there is not an article slug in the URL it will redirect to latest.php.
my PHP code on news.php
$article_slug=$_GET['article_slug'];
if (empty($_GET)) {
header("Location: ../latest.php");
die();// no data passed by get
}
This is what I currently have in my .htaccsess file
Options -MultiViews
RewriteEngine On
RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule ^ - [L]
RewriteRule ^news/([\w\d-]+)$ /news.php?article_slug=$1[QSA,L]
RewriteCond %{QUERY_STRING} article_slug=([\w\d-]+)
RewriteRule ^news$ /news/%1 [R,L]
RewriteRule ^category/([\w-]+)$ /category.php?category_slug=$1&page=$2 [QSA]
When I try to debug this myself (with very little knowledge) and add the following line it redirects to latest.php
RewriteRule ^([^/]*)/?$ /news.php [L,QSA]
but on the redirected page I get the following error
The page isn’t redirecting properly
Firefox has detected that the server is redirecting the request for this
address in a way that will never complete.
This problem can sometimes be caused by disabling or refusing to accept cookies
When I use the developer tools in firefox as IMSoP commented all I see is latest.php reloaded multiple times.
This is not just isolated to just latest.php but any file on the server thats not listed in the access file
when I remove the line
RewriteRule ^([^/]*)/?$ /news.php [L,QSA]
I can load the PHP file but it doesn't redirect from news.php and http://localhost/news is not found but http://localhost/news/example-1 works.
but when I go to http://localhost/news i get a 404 error.
None of your rules catch such a request, so no rewriting occurs and you get a 404.
RewriteRule ^([^/]*)/?$ /news.php [L,QSA]
This rewrites everything to /news.php, including /latest.php that you are redirecting to in your PHP script and the cycle repeats, resulting in a redirect loop to /latest.php.
However, this redirect in your PHP code would also seem to assume there is a slash on the original request. ie. should be /news/ (with trailing slash) not /news (no trailing slash) as you state in the question.
It would be better to redirect to a root-relative (or absolute URL) in your PHP script. ie. header('Location: /latest.php');
RewriteRule ^news/([\w\d-]+)$ /news.php?article_slug=$1[QSA,L]
RewriteCond %{QUERY_STRING} article_slug=([\w\d-]+)
RewriteRule ^news$ /news/%1 [R,L]
(Note you are missing a space before the "flags" argument in the first rule.)
The first rule can be modified to allow news/ and not just news/<something>. This is achieved by simply changing the quantifier from + (1 or more) to * (0 or more) on the capturing subpattern.
The second rule is not currently doing anything. You should probably be targeting news.php here. But the rules are also in the wrong order.
As noted in my answer to your earlier question, the \d shorthand character class is not necessary, since \w (word characters) already includes digits.
Try the following instead:
RewriteCond %{QUERY_STRING} (?:^|&)article_slug=([\w-]*)(?:$|&)
RewriteRule ^news\.php$ /news/%1 [R=301,L]
RewriteRule ^news/([\w-]*)$ /news.php?article_slug=$1 [QSA,L]
Note, the first rule should be a 301 (permanent) redirect, not a 302 (as it was initially). But always test first with a 302 to avoid potential cachining issues.
This allows requests to /news/, but not /news (no trailing slash). Only one of these can be canonical. If you need to handle /news as well then you should redirect to append the trailing slash (so /news/ is canonical, and the URL you should always link to.) For example, before the above two rules:
# Append trailing slash if omitted (canonical redirect)
RewriteRule ^news$ /$0/ [R=301,L]
Summary
Bringing the above points together:
Options -MultiViews
RewriteEngine On
RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule ^ - [L]
# Append trailing slash if omitted (canonical redirect)
RewriteRule ^news$ /$0/ [R=301,L]
RewriteCond %{QUERY_STRING} (?:^|&)article_slug=([\w-]*)(?:$|&)
RewriteRule ^news\.php$ /news/%1 [R=301,L]
RewriteRule ^news/([\w-]*)$ /news.php?article_slug=$1 [QSA,L]
RewriteRule ^category/([\w-]+)$ /category.php?category_slug=$1 [QSA,L]
However, the same now applies to your /category URL. This was also discussed in your earlier question. (I've removed the superfluous &page=$2 part and added the missing L flag.)
If you have many such URLs that follow a similar pattern (eg. news and category etc.) you don't necessarily need a separate rule for each. (An exercise for the reader.)
UPDATE:
$article_slug=$_GET['article_slug'];
if (empty($_GET)) {
header("Location: ../latest.php");
die();// no data passed by get
}
As discussed in comments, this should read:
$article_slug = $_GET['article_slug'] ?? null;
if (empty($article_slug)) {
header("Location: /latest.php");
die(); // no data passed by get
}
Rewrite rules are at heart very simple: they match the requested URL against a pattern, and then define what to do if it matches.
RewriteRule ^([^/]*)/?$ /news.php [L,QSA]
The pattern here translates as "must match right from the start; anything other than a slash, zero or more times; optional slash; must match right to the end". The action if it matches is to act as though the request was for "/news.php", adding on any query string parameters.
That's a very broad pattern; it will match "news" and "news/" but it will also match "hello-world", and "__foo--bar..baz/". The only thing that would stop it matching is other rules higher up your config file.
Meanwhile, every time this rule matches, your PHP code in news.php will run, and if there isn't anything on the query string, will tell the browser to request "latest.php".
But the rule will also match "latest.php". So when the browser requests "latest.php", the code in "news.php" gets run, and tells the browser to request "latest.php" again ... and we have an infinite loop.
The simplest fix is just to make your rule more specific, e.g. look specifically for the word "news":
RewriteRule ^news/?$ /news.php [L,QSA]
Another common technique is to add a condition to the rule that it only matches if the URL doesn't match a real filename, like this:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^/]*)/?$ /news.php [L,QSA]

Redirect rule to php query but remove any query string in the requested url

My url is being redirected using .htaccess as follows:
RewriteRule ^b/([^/]+)/([^/]+)? b/view.php?id=$2&name=$1
Friendly url -> translates to php url
domain.com/b/hello/2 -> b/view.php?id=2&name=hello
BUT when someone comes to the site as follows:
domain.com/b/hello/2?query=xyz
I don't know how to get rid of the ?query=xyz
I have tried everything including [QSD] and I can't seem to get it to work.
Update
I have managed to get it to work with the following but it does two 301 redirects instead of one:
RewriteCond %{THE_REQUEST} \?[^\ ]+
RewriteRule ^b/(.*)$ /x/$1? [R=301,L]
RewriteRule ^b/([^/]+)/([^/]+)/([^/]+)?$ b/view.php?id=$2&&name=$1
Check if adding the question mark at the end of the rule will cancel appending query string from left side
RewriteRule ^b/([^/]+)/([^/]+)? b/view.php?id=$2&name=$1? [QSD,L]
You can use an additional Rule to catch for GET parameters and strip them off.
RewriteCond %{QUERY_STRING} .+
RewriteRule ^(.*)$ /$1? [R=301,L]
RewriteRule ^b/([^/]+)/([^/]+)? b/view.php?id=$2&name=$1
To make it only work on the /b/ subfolder, use this:
RewriteCond %{QUERY_STRING} .+
RewriteRule ^b/(.*)$ b/$1? [R=301,L]
RewriteRule ^b/([^/]+)/([^/]+)? b/view.php?id=$2&name=$1
The first rule will redirect everything that matches your rule to the URL without any GET parameters (note the ? at the end of the rewrite rule, it will strip off the parameters).
The second rule will match in the case the first rule cannot be applied, i.e., when there are no paramaters

.htaccess redirect urls with spaces

I am trying to redirect all invalid urls to my index.php file via my .htaccess file.
Unfortunately I keep getting an Apache error.
My .htaccess file
RewriteEngine on
RewriteCond %{REQUEST_URI} !\.(?:css|js|jpe?g|gif|png)$ [NC]
RewriteRule ^([a-zA-Z0-9\-\_\/]*)$ index.php?p=$1
RewriteRule ^([A-Za-z0-9\s]+)$ index.php?p=$1 [L] 
This invalid url shoud redirect to index.php:
/vacatures/jobapplication/facility-manager%20qsdf
But it throws the object not found 404 Apache error.
The rule you have which allows spaces does not allow hyphens. The rule you have which allows hyphens does not allow spaces. So anything which includes both will not match either.
Your invalid URL facility-manager%20qsdf includes both.
My guess is that your RewriteCond is supposed to apply to both rules, but that is not what is happening now, it will apply only to the first RewriteRule after it. You can solve all these problems by including just 1 RewriteRule, and amending it to accept everything you want:
RewriteRule "^([A-Za-z0-9\-\_\/\s]+)$" index.php?p=$1 [L]
Note that this requires at least one of the characters in your character class, in other words it will not match your "home" location when there is no path ("http://somewhere.com/"). If you want to also match for that location, change the + to a *, to allow 0 or more character matches.
Your rewrite rules do not match the url you indicated. Your REQUEST_URI is
/vacatures/jobapplication/facility-manager%20qsdf
I suspect the URL decoding is not done before the RewriteRule matching and therefore it's trying to match literally %20, yet % sign is not included in your match. I'm not sure why you're using two RewriteRules - why not do something like this?
RewriteEngine on
RewriteCond %{REQUEST_URI} !\.(?:css|js|jpe?g|gif|png)$ [NC]
RewriteCond %{REQUEST_URI} !^index.php(\?.*)?$
RewriteRule ^(.*)$ index.php?p=$1 [L]

Removing the last slash from query parameter using .htaccess

I want to remove the last slash character from query parameter's value using .htaccess.
Suppose I have the following URL:
www.example.com/?key_=/job_category/mobile/
Then from /job_category/mobile/ I want to remove the last slash.
After removing the last slash, it would redirect to www.example.com/snapshots/job_category/mobile.html, but with my current settings it redirects to www.example.com/snapshots/job_category/mobile/.html.
My current .htaccess file looks like this:
RewriteEngine On
RewriteCond %{QUERY_STRING} ^key_=(.*)$
RewriteRule ^(.*)$ snapshots/%1.html [R=301,QSD]
You don't need to capture anything in RewriteRule, as all necessary information is already captured by RewriteCond. To remove the trailing slash use an expression like \/*$ (zero or more slashes at the end):
RewriteEngine on
RewriteCond %{QUERY_STRING} ^key_=(.*?)\/*$
RewriteRule ^.*$ /snapshot%1.html [R=301,QSD]

Mod rewrite issue redirect with post

In fact I am working on a small php script, and now I am struggling with doing redirect using mod-rewrite.
What i want is to redirect
www.xx.com/motivational/api.php?latest=1
to
www.xx.com/api.php?latest=1&app=motivational
I tried this but it doesn't work:
RewriteRule ^/motivational/api\.php$ /api.php?latest=&%{QUERY_STRING}
%{QUERY_STRING} represents the entire query string, in your case latest=1. So when you append it to ...?latest= in your substitution string the result is ...?latest=latest=1 which is not what you want.
Change your rule to
RewriteRule ^/motivational/api\.php$ /api.php?%{QUERY_STRING}&app=motivational
and you should be fine.
Or you could do:
RewriteRule ^/motivational/api\.php$ /api.php?app=motivational [QSA]
The QSA flag means to append the new query string to the old, rather than to replace it, so your latest variable will not be lost.
You can not match against query strings in a RewriteRule, You will need a RewriteCond to match query strings in url :
RewriteEngine on
RewriteCond %{THE_REQUEST} /([^/]+)/api\.php\?latest=1 [NC]
RewriteRule ^ /api.php?latest=1&app=%1 [NC,L,R]
%1 is part of the regex "([^/]+)" in RewriteCond, it contains dynmically captured path in the request line.

Categories