htaccess rewrite rule from folder to folder with querystring - apache

I am looking to include a rewrite rule for the following but can't seem to get it to work. I don't want to pass any query string in but I need to add one to the rule.
I want this URL:
https://example.co.uk/vehicles/
to point to:
https://example.co.uk/search-results/?category=1
but keep the first URL in the address bar.
I need to pass in a variable called category with a value.
I tried the following but it didn't work for me:
rewriterule ^vehicles/$ search-results/?category=1 [NC, L]
Any help would be appreciated.
RewriteEngine On
RewriteRule .* ? [F,L]
RewriteRule ^(.*)$ https://example.co.uk/$1 [R,L]
RewriteRule ^ad/(.*/)?([0-9]+)$ view-ad/?ad=$2 [NC,L]
RewriteRule ^vehicles/$ search-results/?category=1 [NC,L]

I managed to solve it. It was due to an Ajax load on the page.
Glad you solved your initial query, however, the following two directives in your posted .htaccess file will break your site, so presumably, these have already been removed?
RewriteRule .* ? [F,L]
RewriteRule ^(.*)$ https://example.co.uk/$1 [R,L]
The first directive simply blocks all access to your site, returning a 403 Forbidden response. And the second directive will result in a redirect loop.
Now that it works is it possible to have another rewrite rule that does this https://example.co.uk/vehicles/?something=1 and rewrite to https://example.co.uk/vehicles/?category=1&appendsomething=1 but only display https://example.co.uk/vehicles/
I assume you mean https://example.co.uk/search-results/?category=1&something=1 (as opposed to /vehicles/) - where something=1 is appended on the end of the query string?
You wouldn't be able to make this "display as https://example.co.uk/vehicles/" - as this would conflict with your existing (working) directive.
However, you could potentially modify your existing directive to handle requests for /?something=1 and pass this through to the substitution. This would simply require the addition of the QSA flag (Query String Append). For example:
RewriteRule ^vehicles/$ search-results/?category=1 [QSA,NC,L]
The QSA flag results in the query string from the request being appended to the end of the query string specified in the RewriteRule substitution.
UPDATE: To redirect HTTP to HTTPS, you would need something like the following instead:
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://example.co.uk/$1 [R,L]
Note the preceding RewriteCond directive - this ensures that only HTTP requests are redirected, not everything (HTTP and HTTPS), so avoiding a redirect loop. Ultimately this should also be a 301 (permanent) redirect, so you should change R to R=301, but only when you are sure it's working OK.

Related

.htaccess RewriteRule from long url to show short url

Im trying to rewrite url from long to short but cant wrap my head around this.
My survey rewrite works wonderfully but after completing my survet php redirects to www.example.com/survey_thank_you.php?survey_id=1
but I would like to show url like www.example.com/thank_you
Im not even sure if this is possible.
Im new with .htaccess and i have tried almost everthing
.htaccess
Options +FollowSymLinks
Options -MultiViews
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^survey_thank_you.php?survey_name=([0-9a-zA-Z]+)/?$ Thank_you [L,NC,QSA]
RewriteRule ^([0-9a-zA-Z]+)/?$ survey_form.php?survey_name=$1 [L,NC,QSA] #works like charm.
Any help or directions will be highly appreciated.
Solution:
Options +FollowSymLinks
Options -MultiViews
RewriteEngine on
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} ^survey_id=([0-9a-zA-Z]+)/?$
RewriteRule ^survey_thank_you\.php$ /%1/thank_you [R,L,QSD]
RewriteRule ^([0-9a-zA-Z]+)/thank_you$ survey_thank_you.php?survey_id=$1 [L,NC,QSA]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^([0-9a-zA-Z]+)/?$ survey_form.php?survey_name=$1 [L,NC,QSA]
but after completing my survet php redirects to www.example.com/survey_thank_you.php?survey_id=1
You need to "correct" the URL that PHP is redirecting you to after the survey. If the desired URL is /thank_you (or /Thank_you?) then PHP should be redirecting to that URL.
You then use mod_rewrite in .htaccess to internally rewrite /thank_you back into the URL that your application understands. ie. /survey_thank_you.php?survey_id=1. However, therein lies another problem, where does the 1 (survey_id) come from in the query string? Presumably you don't want to hardcode this? So this would need to passed in the requested URL. eg. /1/thank_you or perhaps /thank_you/1?
However, is this really necessary? The resulting "thank you" page is not a page that should be indexed or a page that is normally navigated to by the user, so implementing a user-friendly URL here doesn't seem to be a worthwhile exercise?
RewriteRule ^survey_thank_you.php?survey_name=([0-9a-zA-Z]+)/?$ Thank_you [L,NC,QSA]
RewriteRule ^([0-9a-zA-Z]+)/?$ survey_form.php?survey_name=$1 [L,NC,QSA] #works like charm.
You are using a survey_name URL parameter (referencing an alphanumeric value) in your directives, but a survey_id ("numeric"?) URL parameter in your earlier example? So, which is it? Or are these rules unrelated?
You state that the second rule "works like charm", but how? What URL are you requesting? That would seem to rewrite /Thank_you to survey_form.php?survey_name=Thank_you - but that does not look correct?
As mentioned in comments, the RewriteRule pattern matches against the URL-path only. To match against the query string you need an additional condition that matches against the QUERY_STRING server variable. This would also need to be an external 3xx redirect, not an internal rewrite (in order to change the URL that the user sees). Therein lies another problem... if you don't change the URL that your PHP script is redirecting to then users will experience two redirects after submitting the form.
You also need to be careful to avoid a redirect loop, since you are internally rewriting the request in the opposite direction. You need to prevent the redirect being triggered after the request is rewritten. ie. Only redirect direct requests from the user should be redirected.
So, to answer your specific question, it should be rewritten something like this instead:
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} ^survey_name=[0-9a-zA-Z]+/?$
RewriteRule ^survey_thank_you\.php$ /Thank_you [QSD,R,L]
The check against the REDIRECT_STATUS environment variable ensures that only direct requests are processed, not internally rewritten requests by the later rewrite. REDIRECT_STATUS is empty on the initial request and set to the string 200 (as in 200 OK status) after the first successful rewrite.
The QSD flag (Apache 2.4) is necessary to discard the original query string from the redirect response.
So the above would redirect /survey_thank_you.php?survey_name=<something> to /Thank_you.
But this is losing the "survey_name" (or survey_id?), so should perhaps be more like the following, in order to preserve the "survey_name":
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} ^survey_name=([0-9a-zA-Z]+)/?$
RewriteRule ^survey_thank_you\.php$ /%1/Thank_you [QSD,R,L]
Where %1 is a backreference to the value of the survey_name URL parameter captured in the preceding CondPattern.
However, you would then need to modify your rewrite that turns this back into an understandable URL.
(But you should probably not be doing this in the first place without first changing the actual URLs in the application.)

ModRewrite: QUERY_STRING not redirecting

I have the following rewrite rules in place:
RewriteEngine on
RewriteCond %{QUERY_STRING} ^manufacturer=&
RewriteRule (.*) $1? [R=410,L]
But it doesn't seem to work. I'm trying to redirect with URL's like
http://www.example.com/?manufacturer=someone to http://www.example.com/ and page.php?manufacturer=someone to page.php
What am I doing wrong?
EDIT:
I have mod_rewite enabled and AllowOverride All in my site config
The above code is in the .htaccess file
The query string ^manufacturer=& only matches manufacturer parameters that are empty and it also requires that the equals sign is followed by an ampersand which doesn't seem to be your wanted behaviour.
By the way, you do realize the status code 410 means that the resource is Gone (indicates that the resource requested is no longer available and will not be available again)?
You seem to want to redirect back to the current page without the query parameter, so I suggest using a 302 or 301 redirect instead.
Try this:
RewriteEngine on
RewriteCond %{QUERY_STRING} ^manufacturer=.+$
RewriteRule .* $0? [R=301,L]

How to add "everything else" rule to mod_rewrite

How can I make mod_rewrite redirect to a certain page or probably just throw 404 if no other rules have been satisfied? Here's what I have in my .htaccess file:
RewriteEngine on
RewriteRule ^\. / [F,QSA,L]
RewriteRule ^3rdparty(/.*)$ / [F,QSA,L]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^((images|upload)/.+|style.css)$ $1 [L]
RewriteRule ^$ special [QSA]
RewriteRule ^(special|ready|building|feedback)/?$ $1.php [QSA,L]
RewriteRule ^(ready|building)/(\d+)/?$ show_property.php?type=$1&property_id=$2 [QSA,L]
RewriteRule . error.php?code=404 [QSA,L]
This is supposed, among other things, to send user to error.php if he tries to access anything that was not explicitly specified here (by the way, what is the proper way to throw 404?). However, instead it sends user from every page to error.php. If I remove the last rule, everything else works.
What am I doing wrong?
What is happening is that when you are doing a rewrite, you then send the user to the new URL, where these rewrite rules are then evaluated again. Eventually no other redirectoin rules will be triggered and it will get to the final rule and always redirect to the error.php page.
So you need to put some rewrite conditions in place to make this not happen.
The rewrite engine loops, so you need to pasthrough successful rewrites before finally rewriting to error.php. Maybe something like:
RewriteCond %{REQUEST_URI} !^/$
RewriteCond %{REQUEST_URI} !^/(special|ready|building|feedback|show_property)\.php
RewriteCond %{REQUEST_URI} !^/((images|upload)/.+|style.css)$
RewriteRule ^ error.php?code=404 [QSA,L,R=404]
Each condition makes sure the URI isn't one of the ones your other rules have rewritten to.
The R=404 will redirect to the error.php page as a "404 Not Found".
Unfortunatelly, it didn't work - it allows access to all files on the server (presumably because all conditions need to be satisfied). I tried an alternate solution:
Something else must be slipping through, eventhough when I tested your rules plus these at the end in a blank htaccess file, it seems to work. Something else you can try which is a little less nice but since you don't actually redirect the browser anywhere, it would be hidden from clients.
You have a QSA flag at the end of all your rules, you could add a unique param to the query string after you've applied a rule, then just check against that. Example:
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^((images|upload)/.+|style.css)$ $1?_ok [L,QSA]
then at the end:
RewriteCond %{QUERY_STRING} !_ok
RewriteRule ^ error.php?code=404&_ok [QSA,L,R=404]
In theory if none of the rules are matched (and the requested URL does not exist), it's already a 404. So I think the simplest solution is to use an ErrorDocument, then rewrite it:
RewriteEngine On
ErrorDocument 404 /404.php
RewriteRule ^404.php$ error.php?code=404 [L]
# All your other rules here...
You can do the same for any other HTTP error code.
The problem here is that after the mod_rewrite finishes rewriting the URL, it is resubmitted to the mod_rewrite for another pass. So, the [L] flag only makes the rule last for the current pass. As much better explained in this question, mod_rewrite starting from Apache version 2.3.9, now supports another flag - [END], that makes the current mod_rewrite pass the last one. For Apache 2.2 a number of solutions are offered, but since one of them was a bit clumsy and another didn't work, my current solution is to add another two rules that allow a specific set of files to be accessed while sending 404 for everything else:
RewriteRule ^((images|upload)/.+|style.css|(special|ready|building|feedback|property).php)$ - [QSA,L]
RewriteRule .* - [QSA,L,R=404]
I think your last rule should be
RewriteRule ^(.*)$ error.php?code=404&query=$1 [QSA,L]
You could leave out the parenthesis and the $1 parameter, but maybe it's useful to know, what the user tried to achieve.
Hope, this does the trick!

Redirecting to same page with .htaccess

From my .htaccess file:
RewriteRule ^showPAGE.php page [NC,R=301]
RewriteRule ^page showPAGE.php [NC,L]
I want users going to url domain.com/showPAGE.php to be redirected to domain.com/page .
When domain.com/page is being entered, I want it to show the content of the file showPAGE.php.
Is that possible to do?
The above results an infinite redirection loop.
Thanks
You're trying to do something that's very tricky. The problem is that, by design, the RedirectRule directive always triggers again the complete set of rules. You can only get out of the loop when you obtain a final URL that does not match any of the rules and that's the tricky part since you are reusing the showPAGE.php name.
My best attempt so far involves adding a fake hidden string:
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/showPAGE\.php
RewriteCond %{QUERY_STRING} !^internal
RewriteRule ^ http://%{HTTP_HOST}/page [NC,R=301,L]
RewriteRule ^page$ showPAGE.php?internal [NC,L]
It works but it's not pleasant. Definitively, it's easier to handle the redirection from with PHP or to simply pick another name.
The redirect from showPAGE.php to page needs to have [L] so that it will stop processing and redirect at once, rather than going on and applying other rules (which at once map it back to showPAGE.php). Try this:
RewriteRule ^showPAGE.php page [NC,R=301,L]
RewriteRule ^page showPAGE.php [NC,L]

mod_rewrite weird problem

I have a strange problem with mod_rewrite, the rules that are relevant here are:
RewriteRule ^(.*)\/igre\-(.*)\.php\?Page=([0-9]+)$ game.php?GameUrl=$2&Page=$3 [L]
RewriteRule ^(.*)\/igre\-(.*)\.php$ game.php?GameUrl=$2&Page=1 [L]
And a corresponding URL might look something like this:
example.com/miselne-igre/igre-shirk.php?Page=2
example.com/miselne-igre/igre-shirk.php
The problem is that the first rule has no effect. If I use the first URL from the example I always get 1 into the Page variable, which shows that the second rule is used.
So what's wrong with the first one? And why is the second rule even matching a URL with ".php?Page=XYZ" at the end, if I said that the URL ends with ".php"?
ps: other rules in the .htaccess file are working fine...
The query string is not part of the URI path that is being processed by the RewriteRule directive. You have to use the RewriteCond directive to process the query string.
RewriteCond %{QUERY_STRING} ^Page=[0-9]+$
RewriteRule ^[^/]+/igre-([^/]+)\.php$ game.php?GameUrl=$1&%0 [L]
RewriteRule ^[^/]+/igre-([^/]+)\.php$ game.php?GameUrl=$1&Page=1 [L]
But you can still simplify this by using the QSA flag (query string append):
RewriteRule ^[^/]+/igre-([^/]+)\.php$ game.php?GameUrl=$1 [L,QSA]
mod_rewrite is not using the query in it's rewriting process. Therefor you first RewriteRule is ignored. You could combine it with a RewriteCond (haven't tested it though) like so:
RewriteCond %{QUERY_STRING} Page=([0-9]+)
RewriteRule ^(.*)\/igre\-(.*)\.php\?Page=([0-9]+)$ game.php?GameUrl=$2 [L, qsappend]
# qsappend appends the original query, in this case (Page=xx)
Ah, like Gumbo said; you can also use %1 to back reference to the page numer.
Is it just me or are your arguments back-to-front?
Do you mean:
RewriteRule ^(.*)\/(.*)\-igre\.php\?Page=([0-9]+)$ game.php?GameUrl=$2&Page=$3 [L]
RewriteRule ^(.*)\/(.*)\-igre\.php$ game.php?GameUrl=$2&Page=1 [L]
You wanted to match miselne-igre not igre-miselne.
Obviously this doesn't address the main issue, but thought I'd throw that in.
Dom