I have a Rewrite Rule as
RewriteRule settings/([a-zA-Z0-9_]+)/?$ settings/?path=$1 [NC,L,QSA]
It basically takes path parameter and rewrite url like this
http://localhost/settings/?path=abc => http://localhost/settings/abc
But there's a problem! when I provide something like http://localhost/settings/abc/?path=xyz the path parameter is overwritten with xyz and it opens http://localhost/settings/abc/ with data of xyz
After further digging I noticed that the problem is caused by the parameters in URL itself. By default its picking up the value of last parameter with same name http://localhost/settings/account/?path=profile&path=account&path=profile
so the value that i can get in this case for $_REQUEST['path'] is profile. How can I just pickup the first value from the same parameters and ignore the rest of them?
One thing I can do is to remove [QSA] from the RewriteRule, that will do the fix but I need other parameters passed in url as well.
How can I achieve this?
PHP recognizes brackets [] appended to a parameter, e.g.
http://localhost/settings/account/?path[]=profile&path[]=account&path[]=profile
will be translated into an array
$path = $_GET['path'];
print_r($path);
shows
Array ( [0] => profile [1] => account [2] => profile )
This way, you can access any of the "paths" you like.
I could imagine some RewriteCond surgery, in order to remove part of a query string
RewriteCond %{QUERY_STRING} ^(.*)&path=.*?&(.*)$
RewriteRule ^ %{REQUEST_URI}?%1&%2
RewriteCond %{QUERY_STRING} ^path=.*?&(.*)$
RewriteRule ^ %{REQUEST_URI}?%1
RewriteCond %{QUERY_STRING} ^(.*)&path=.*$
RewriteRule ^ %{REQUEST_URI}?%1
Depending on where the path is, this would remove it from the query string. And finally, the last rule would add the new path again
RewriteRule settings/([a-zA-Z0-9_]+)/?$ settings/?path=$1 [NC,L,QSA]
Although, I don't know, if this is working at all, and how (in)efficient this is.
There is one caveat, you must check for REDIRECT_STATUS to prevent an endless loop.
You can use these 2 rules in your .htaccess:
# remove path= parameter from query string, if it exists
RewriteCond %{THE_REQUEST} \?(.*&)?path=[^&]*(?:&(.*))?$ [NC]
RewriteRule ^settings/. %{REQUEST_URI}?%1%2 [L,R=301,NE,NC]
# your existing rule
RewriteCond %{THE_REQUEST} \?(.*&)?path=[^&]*(?:&(\S*))? [NC]
RewriteRule ^settings/ %{REQUEST_URI}?%1%2 [L,R=302,NE,NC]
RewriteCond %{QUERY_STRING} !(?:^|&)path= [NC]
RewriteRule ^(settings)/(\w*)/?$ $1/?path=$2 [NC,L,QSA]
Related
I would like to know how I can get a second parameter when I load data from an htaccess, I have everything working so that I get the first parameter that is the subdomain, the second parameter would be the "GET" that it gets from the URL, for example:
I want to load:
subdomain.domain.com/category?idx=22
With the following code I get the first parameter that is the subdomain but I can't get the idx after category
This is the code:
RewriteCond %{HTTP_HOST} !^(www\.)?domain.com$ [NC]
RewriteCond %{HTTP_HOST} ^([^.]+)\.domain.com$ [NC]
RewriteCond "%{REQUEST_URI} /%1" !^(/[^/]+)[^\s]*\s\1$
RewriteRule ^category$ loader-category.php?&id=%1&idx=$2 [L]
what's the correct regex for this?
I appreciate any help
RewriteRule ^category$ loader-category.php?&id=%1&idx=$2 [L]
What would $2 be referring to here? You don’t have any capturing groups in the pattern.
Use the QSA flag here, so that the original query string gets appended / merged with the new one you are creating.
https://httpd.apache.org/docs/2.4/rewrite/flags.html#flag_qsa
RewriteRule ^category$ loader-category.php?id=%1 [L,QSA]
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
I'm trying to take a URL with multiple querystring parameters into a folder structure URL and am getting a 500 internal server error.
My incoming URL looks like
www.fivestarprofessional.com/ag?PY=16&PF=wm&MKT=Delaware
My destination URL I need written as
delaware.fivestarprofessional.com/16/wm/index.html
I created 3 RewriteCond statements to capture the parameters and a RewriteRule to create the output
RewriteCond %{QUERY_STRING} !^(PY=.*)$ [NC]
RewriteCond %{QUERY_STRING} !^(PF=.*)$ [NC]
RewriteCond %{QUERY_STRING} !^(MKT=.*)$ [NC]
RewriteRule %3.fivestarprofessional.com/%1/%2/index.html
Any assistance would be greatly appreciated.
You can use this rule for your redirection:
RewriteCond %{QUERY_STRING} (?:^|&)PY=([^&]+) [NC]
RewriteCond %1::%{QUERY_STRING} (.*?)::(?:|.*&)PF=([^&]+) [NC]
RewriteCond %1/%2::%{QUERY_STRING} (.*?)::(?:|.*&)MKT=([^&]+)
RewriteRule ^ag/?$ http://%2.fivestarprofessional.com/%1/index.html? [L,NC,NE,R=302]
% variables are captured only from the most recent condition using same %{QUERY_STRING}
Try this one:
RewriteCond "%{QUERY_STRING}" "^PY=([^&]+).*&PF=([^&]+).*&MKT=([^&]+)" [NC]
RewriteRule "www.fivestarprofessional.com/ag" "%3.fivestarprofessional.com/%1/%2/index.html"
The following issues have been corrected:
RewriteRule takes 3 arguments instead of 2.
Arguments to RewriteCond hadn't been enclosed in quotes.
The backreferences into the RewriteCond rules ...
... only refer to the last condition matched (pointed out by #anubhava, being documented in the apache httpd docs). Therefore, the rules need to be collapsed in one.
... referred to the parameter name plus the complete remainder of the query string
... would have matched against query string starting with the respective ul parameter due to the use of the ^ anchor.
... would have been empty anyway, as the rules fired when the patterns did not match ( use of ! prefix )
Recommended reading is the proper section of the apache httpd documentation.
The solution as it stands assumes that...
the query string starts with the url parameter PY
the order in which the url parameters PY, PF, MKT appear in the query string is fixed.
I got this url:
somesite.org/news.php?a=0&b=20
What I want - redirect it to
somesite.org/specialnews/20
If you see - key a means the type. So a=0 means specialnews. So I need redirect only those urls, that have a=0 and base url (news.php) also to /specialnews/.
What I've tried is:
RewriteCond %{QUERY_STRING} ^a=0&b=(.*)$
RewriteRule ^news\.php\?a\=0&b\=(.*)$ specialnews/$2 [R=301]
didn't help ;)
Need directions.
You can't match query string params in RewriteRule, but you can capture paramters via RewriteCond and use it (with %) in RewriteRule:
RewriteCond %{QUERY_STRING} a=0&b=(.*)
RewriteRule ^news.php /specialnews/%1? [R=301]
I need to be able to shorten my page from:
mydomain.com/mixtape.php?mixid=(WHATEVER NUMBER)
To:
mydomain.com/m/(WHATEVER NUMBER)
Now usually this wouldn't be much of an issue for me to figure out, but becasue of a few pre-existing functions in my .htaccess file, it is really hard for this function not to improperly interact with the others.
Below is the current code of my .htaccess file (AND NONE OF IT CAN CHANGE)
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/\.]+)/?$ profile.php?user=$1 [L]
Above, the .htaccess file is shorting my
mydomain.com/profile.php?username=(USERNAME)
to
mydomain.com/(USERNAME)
Is there anyone out there than can help me by being able to shorten the m/index.php?mixid and not have it conflict with the pre-existing function?
Prepend this rule to your .htaccess block rewriting the profile url (after turning the rewrite engine on) :
RewriteCond $1 ^m/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ mix.php?id=$1 [L]
That rule will now only be used for URLS like :
mydomain.com/m/(WHATEVER NUMBER)
The first line is a condition that the incoming URL must start with m/
The second and third lines are conditions that the incoming URL does not represent an actual file or folder (we wouldn't want our humble rewrite rule to block us from a real resource).
The fourth line is the actual rule itself witch uses a regular expression syntax to match and capture everything that appears after host name and passes it to the mixtape.php file as a GET parameter called id. This line also contains the [L] flag which states that no more rules or rewriting will occur on the current incoming URL.
In your mix.php file you can use the explode method to split the resulting string into an array :
http://example.com/m/foo/bar =>
`http://example.com/mixtape.php?id=/m/foo/bar
$splitArr = explode('/',$_GET['id']);
$splitArr =>
array (
0 => 'm',
1 => 'foo',
1 => 'bar',
)
and remove the initial m with
array_shift();
Then you are left with $splitArr containing all the parts of your URL, split with a / (slash) delimiter.
The URL example.com/m/foo/bar would look like :
array (
0 => 'foo',
1 => 'bar',
)
It is important to place this rule before the existing one as the existing rule will act on any incoming URL. The final two rules that you have should appear like this :
RewriteEngine on
RewriteCond $1 ^m/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ mix.php?id=$1 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/\.]+)/?$ profile.php?user=$1 [L]
Regarding your statement :
AND NONE OF IT CAN CHANGE
I would seriously recommend that you consider implementing a small change on that first rule. Making the final url something like mydomain.com/users/(USERNAME) (as they do here). In these cases it is much better to be more specific than overly general (as the current rule is). Have you considered the confusion that could be created if someone was to chose a user name such as :
about
faq
home
While perfectly valid usernames these users profiles would be :
mydomain.com/about
mydomain.com/faq
mydomain.com/home
Those usernames will block important URLs that you might want to save for other locations on your site. I think it is clear why those user names would be undesirable.
RewriteRule ^m/([0-9]+)$ /mixtape.php?mixid=$1
Put in before or after the existing rule. Should not cause any conflict.