mod_rewrite this - multiple conditions or can I just pass all vars over together? - apache

Due to a reverse proxy setup I'm having to pass an extra query var which the proxy can't using mod_rewrite. The proxy is at /search however I'm using /find on all pages as a mod_rewrite to /search to pas the query var s=gsacollection.
See example:
# Direct link to search which passes collection var
# eg http://www.domain.com/find
RewriteRule ^find$ /search?s=gsacollection [NC]
#Rewrite all query vars
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^find(.*)$ /search?%1 [NC,L]
I'm trying to capture multiple variables for mod_rewrite that are being sent. The issue is I don't always know which ones are being sent over. This is an attempt to blanket capture them. Suggestions?
I want to pass all the query strings after /find? to /search?
EG here are some sample URIs coming in:
find?q=test&sort=date:D:L:d1&num=10&s=gsacollection&l=en&start=10
find?q=tfsa&sort=date:D:L:d1&num=10&s=gsacollection&l=en&filter=0
find?q=tfsa&filter=0&num=10&s=gsacollection&l=en&sort=date%3AD%3AS%3Ad1
If a blanket capture won't work then I will have to look at setting up multiple RewriteCond rules, wondering if there's a way I can combine these in a way I can pass vars from each condition to build the rewrite rule (eg group)?
# Grab everything after /find and replace with /search if these query vars exist
RewriteCond %{QUERY_STRING} q=(.*) [AND]
RewriteCond %{QUERY_STRING} s=(.*)
RewriteRule ^find(.*)$ /search$1

Try using this code in your .htaccess file under $DOCUMENT_ROOT:
Options +FollowSymLinks -MultiViews
RewriteEngine on
RewriteOptions MaxRedirects=10
RewriteRule ^find/?$ search?s=gsacollection [QSA,L,NC]
Make sure you don't have any other conflicting mod_rewrite rule here. QSA flag will make sure to append all query parameters to merge with s=gsacollection parameter.

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.)

Editing .htaccess file to modify URL

I'm trying to modify my .htaccess file to modify my URL and have tried many methods but cannot achieve exactly what I want. For example I have this URL:
http://mywebsite.com/FOLDER/index.php?id=5
Now I want it to look like:
http://mywebsite.com/FOLDER/5
or
http://mywebsite.com/FOLDER/ID/5
My .htaccess contains the following code:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^index/([0-9]+)/([0-9a-zA-Z_-]+) index.php?id=$1 [NC]
I cannot figure out what's wrong. Thanks.
You can use:
RewriteEngine on
# external redirect from actual URL to pretty one
RewriteCond %{THE_REQUEST} \s/+FOLDER/index\.php\?id=(\d+) [NC]
RewriteRule ^ /FOLDER/%1? [R=301,L,NE]
# internal forward from pretty URL to actual one
RewriteRule ^FOLDER/(\d+)/?$ FOLDER/index.php?id=$1 [L,QSA,NC]
The first argument of RewriteRule is what the incoming url without domain and without preceding paths (more on that later) is going to be matched against. This url is, in your case, http://mywebsite.com/FOLDER/5. Assuming that your .htaccess file is in your DocumentRoot, the regex will match against FOLDER/5.
You are currently trying to match FOLDER/5 with ^index/([0-9]+)/([0-9a-zA-Z_-]+), which is not going to work. A better regex would be ^(.*)/([0-9]+)$ or ^(.*)/ID/([0-9]+)$. You can then rewrite to $1/index.php?id=$2. I would recommend using the [L] flag to stop rewriting for this round to avoid common problems with multiple rules matching while you do not expect them to.
Besides this, make sure that your .htaccess files are being read (e.g. by checking that if you enter garbage, you get a 500 internal server error), that mod_rewrite is enabled, that you are allowed to override FileInfo. You also may need to turn AcceptPathInfo off.

Apache rewrite Subdirectories URL Internally Redirect to Query String

I want to make apache rewrite all links in the form :
host.com/links/<a>/<b>/<c>
such as :
host.com/links/1/2/3
To the form :
host.com/links/?a=1&b=2&c=3
I understand i need to add .htaccess with rewriting rules to links folder but dont really understand the syntax of the rewriting rules.
can any one help?
According to this link
The URL in the browser would be:
host.com/links/1/2/3
The actual page rendered by the server would be:
host.com/links/?a=1&b=2&c=3
Add to .htaccess this lines:
RewriteEngine On
RewriteRule ^/links/([^/]+)/([^/]+)/([^/]+) /?a=$1&b=$2&c=$3 [PT]
When you want to rewrite more complex URLs, you need to create more
complex regular expressions. Just about any pattern can be expressed
as a regular expression, if you break it down into small chunks. This
regular expression breaks down into just a few component parts, once
you get past staring at the seemingly random characters:
[^/]
The above component is a character class containing a "not slash".
So, if we do ...
[^/]*
that means "zero or more not-slash characters". In other words, we're
looking for everything between the slashes. There are two sets of
these, because we're looking for two blocks of things between slashes.
Armed with that little nugget of information, go look at the regular
expression again and see if it makes a little more sense. As with the
earlier , I used the [PT] flag to indicate that the target URL was not
merely a file to be served, but was something that needed to be
handled. In this case, it's going to be a cgi-script handler. So
Apache passes the resulting URL through to that handler.
The basci syntax of rewriting rule is to be followed like below.
Enable mod_rewrite and .htaccess through httpd.conf and then put this code in your .htaccess under DOCUMENT_ROOT directory
Options +FollowSymLinks -MultiViews
# Turn mod_rewrite on
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^(demo)\.(.+)$ [NC]
RewriteRule ^(setup)/?$ http://www.%2/%1/$1 [L,R=301,NC]
RewriteCond %{HTTP_HOST} ^(demo)\.(.+)$ [NC]
RewriteRule ^(xyz)/?$ http://www.%2/%1/web/$1 [L,R=301,NC]
RewriteCond %{HTTP_HOST} !^demo\. [NC]
RewriteRule ^(xyz)/?$ /web/$1 [L,R=301,NC]
For more informations about rewrite flags
https://httpd.apache.org/docs/2.4/rewrite/flags.html
https://httpd.apache.org/docs/2.4/rewrite/intro.html

htaccess rewrite rule from folder to folder with querystring

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.

Apache rewrite - match query string

I understand that using rewrites in apache if i want to match the query string then i should use
RewriteCond %{QUERY_STRING}
Which is fine, however, I have a csv with around 2000 urls to rewrite, a lot contain random query strings. It will be a painstaking process to go through each and create the rule.
Is there any generic way to have the rewrite look at the entire url, including the query string and redirect it?
try rewritemap
example config for vurtual host
RewriteEngine on
RewriteMap mymap "txt:/path/to/map.txt"
RewriteCond %{QUERY_STRING} ^(.+)$
RewriteCond ${mymap:%1} >""
RewriteRule ^(.*)$ ${mymap:%1} [L]
and map.txt example
p=1&i=1 /test.php?n=2
p=1&i=2 /test.php?n=4
p=1&i=3 /test.php?n=6
...
Suppose that it is suitable for site with no hign load :)