.htaccess 301 and PHP query string - php

I'm wondering if the wonderful world of the SO community can help me with this one.
I have the following URL's that I would like to redirect/rewrite in my .htaccess file.
1. Redirect
I am trying to 301 redirect this URL:
http://example.com/staff-view.php?i=ACCOUNT_ID_EXAMPLE
to
http://example.com/staff-view/ACCOUNT_ID_EXAMPLE/
I have attempted the following:
RewriteEngine On
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s/+staff-view\.php\?i=([^\s]+) [NC]
RewriteRule ^ /staff-view/%1/? [R=301,L]
however when navigating to the from URL it does not redirect.
2. PHP Query String
I am using the below to rewrite:
RewriteRule ^staff-view/([^/]+)/?$ /staff-view.php?i=$1 [L,QSA,NC]
and accessing through URL
http://example.com/staff-view/ACCOUNT_ID_EXAMPLE/
it correctly directs me to the right page, but when attempting to access ACCOUNT_ID_EXAMPLE via the following methods:
<?
var_dump($_REQUEST);
var_dump($_GET);
?>
They both are empty:
array(0) { } array(0) { }
I would appreciate any help, if you need any more info, please let me know.
Update 1
Updated .htaccess file:
RewriteEngine On
RewriteRule ^staff/([^/]+)/?$ /staff-view.php?i=$1 [L,QSA,NC]
RewriteBase "/"
RewriteCond %{REQUEST_URI} ^staff-view\.php$
RewriteCond %{QUERY_STRING} ^i=([A-Z0-9_]*)$
RewriteRule ^(.*)$ ^staff/%1/
I have attempted to access the file from:
http://example.com/path/to/site/staff/ACCOUNT_ID
and it DOES NOT work. However, if I access the file from:
http://example2.com/staff/ACCOUNT_ID
it WORKS.
But if I go to http://example2.com/staff-view.php?i=ACCOUNT_ID it does not redirect to http://example2.com/staff/ACCOUNT_ID - this is not the end of the world, but I would like to fix it, but the deep directory issue as a priority :).

Try using this:
RewriteEngine On
RewriteRule ^staff-view/([^/]*)$ /staff-view.php?i=$1 [L]

Trying to parse %{THE_REQUEST} (e.g., "GET /staff-view.php?i=account_id HTTP/1.1") to extract both the path and the query string could work but it's unnecessarily complex. I think it's much simpler to use two rewrite conditions that take advantage of the server variables %{REQUEST_URI} and %{QUERY_STRING} because they are pre-populated with the info you're interested in.
Try the following:
RewriteEngine On
#If you don't have this set in your htaccess,
# Apache may prepend the final path with your on disk dir structure
RewriteBase "/"
#Rewrite if the /staff-view.php page is requested
RewriteCond %{REQUEST_URI} ^/staff-view\.php$
#Rewrite if the query string contains i parameter anywhere. Assumes
# ID can be only digits; include all allowed chars. eg: [a-zA-Z0-9_]
#Don't forget the '&' before {{QUERY_STRING}} otherwise the match
# will fail if i is the first parameter
RewriteCond &%{QUERY_STRING} &i=([0-9]+)
#Rewrite the account ID as part of the path. Append the query string
# in order to preserve other query parameters (eg: if user asked for
# /staff-view.php?i=123&x=boo, you want to preserve x=boo. a 301
# redirect tells the browser to go to the new path and to remember it
#This will stop processing and cause the browser to make a new request
RewriteRule ^(.*)$ /staff-view/%1/ [QSA,R=301,L]
#Finally, we want to silently forward any request matching the last
# redirect target to the actual file that will serve the request.
# The account ID should be of the same format as above: ([0-9]+). The
# [L] flag tells the server to stop looking for new instructions
RewriteRule ^staff-view/([0-9]+)/$ /final.php?i=$1 [QSA,L]
The logic is easy to follow: If the path requested is /staff-view.php, and if the query string contains the i parameter, tell the user's browser to go instead to /staff-view/ID, preserving the other query params. Finally, when the browser asks for this new path, silently (without telling the browser) forward the request to final.php along with the ID and other query params

Related

How to do both internal and external .htacces rewrite to completely remove ALL QUERY_STRING elements from ALL URIs, with relative path

I want to remove all client request querystrings whatsoever, no exceptions.
I have tried everything I can find, and everything I know about regular expressions, and this task puzzles me. I have been able to achieve removal of the query strings, but now all requests have the full file path prepended to the working directory upon rewrite and redirect.
Examples: there is no http in these because stackoverflow won't let me post URLs.
I access the file: /localhost/testing/dogs/pups.txt
Yes, pups.txt exists and lives right there.
Server returns this to browser: /localhost/home/user/public_html/testing/dogs/pups.txt
If I access it with a query string appended:
/localhost/testing/dogs/pups.txt?bark=woof
I get the same output to the browser:
/localhost/home/gost/public_html/testing/dogs/pups.txt
So I know the query string is being nixed, while the full root path is being added to the hypertext address.
How do I tell mod_rewrite to keep the relative path of the existing files, so that this prepending of the full file path stops, and accurately cause it to rewrite internally and externally so that no query string ever makes it to php-land?
Here is the current .htaccess file. It resides in directory /home/user/public_html/testing. Where deployed online, it is NOT possible to put it in the root web directory, the obvious move that would instantly resolve this problem.
# These are commented out on purpose because they kill access to the server.
# The weird rules for regex in Apache configurations is baffling me. This
# does remove all QUERY_STRING characters, but, it then rewrites by
# prepending the web root path to the current directory, causing error 404.
# RewriteCond %{QUERY_STRING} ^
# RewriteRule (.*) $1? [R=301,L]
# These rules work fine. Whatever does not end with a media or document
# extension gets sent to index.php
RewriteRule ^.*\.(gif|jpe?g|png|txt|svg|pdf|rtf|odt|doc|docx)$ - [L]
RewriteRule ^.*\.(tex|epub|mobi|csv|ods|xls|swf|flv)$ - [L]
RewriteRule ^ index.php [L]
Change this RewriteCond %{QUERY_STRING} ^ to this RewriteCond %{QUERY_STRING} .
and add the directory to the rule since you can't use rewritebase. So it should look like this
RewriteCond %{QUERY_STRING} .
RewriteRule (.*) /testing/$1? [R=301,L]
I can't accept my own answer for two days, so if anyone wants to add logic about mod_rewrite for future questioners, have at it. Per Panama Jack's advice, this .htaccess file does the job and this question is answered.
RewriteEngine On
RewriteCond %{QUERY_STRING} .
RewriteRule (.*) /testing/$1? [R=301,L]
RewriteRule ^.*\.(gif|jpe?g|png|txt|svg|pdf|rtf|odt|doc|docx)$ - [L]
RewriteRule ^.*\.(tex|epub|mobi|csv|ods|xls|mm|)$ - [L]
RewriteRule ^ test.php [L]

.htaccess redirect only if GET parameter exists

I have a client with an old website without 'pretty' URLs. So currently it looks like this:
http://www.domain.com/?w=42&a=5&b=3
The parameter values are numbers only.
Now they want to move the old site to a subdomain and main (www) domain would be home to a new website (WP with SEO friendly URLs).
Now what I would like to do is redirect all requests that come to the /?w=<num> (and ONLY those) to sub.domain.com/?w=<num>, so that existing links (mostly from Google) get redirected to the subdomain page, while the new page works serving new content thorough pretty URLs.
I tried this:
# This works, but redirects the entire www.domain.com
# to sub.domain.com no mather what
RewriteCond %{HTTP_HOST} ^www\.domain\.com$ [NC]
RewriteRule ^(.*)$ http://sub.domain.com/$1 [R=301,L]
# But this DOESN'T work
RewriteRule ^/?w(.*) http://sub.domain.com/?w$1 [R=301,L]
# Also tried to redirect 'by hand', but DIDN'T work either
Redirect 301 /?w=42 http://sub.domain.com/?w=42
What am I doing wrong? I searched high and low but always end up with this kind of suggestions. Or maybe I'm just searching for wrong keywords ...
Thank you!
You can't match against the query string inside a rewrite rule or a redirect directive. You need to match against the %{QUERY_STRING} variable. Try:
RewriteCond %{QUERY_STRING} (^|&)w=[0-9]+(&|$)
RewriteRule ^(.*)$ http://sub.domain.com/$1 [L,R=301]
Note that the query string gets automatically appended to the end of the rule's destination.
Just for documentation: If you want to redirect one directory (path) only if there is a URL parameter present, from one path to another, while maintaining the URL parameter, you can use this in your htaccess file:
# /programs/?id=1 to new path /loadprog/?id=1
RewriteCond %{REQUEST_URI} ^/programs/
RewriteCond %{QUERY_STRING} id=
RewriteRule ^programs\/$ /loadprog/$1 [R=301,L]
I am sure this will help others since I stumbled over the question above trying to find this answer.

URL Rewrite for calendar site

I am trying to make the URL for my calendar site look nicer with .htaccess, but I can't get it to work.
I already have a rule, that removes the .php extension, and it works perfect. It looks like this:
RewriteEngine On
# turn on the mod_rewrite engine
RewriteCond %{REQUEST_FILENAME}.php -f
# IF the request filename with .php extension is a file which exists
RewriteCond %{REQUEST_URI} !/$
# AND the request is not for a directory
RewriteRule (.*) $1\.php [L]
# redirect to the php script with the requested filename
My current URL look like this:
http://mydomain.com/calendar/calendar-site?year=2013&month=november
... and I want to make it look like this:
http://mydomain.com/calendar/2013/November
The site works perfect without the rewrite, where I use $_GET[] to get the values for year and month in the URL, but with the rewrite on, it cannot get the values from the url.
I have tried these (not both at once of course):
RewriteRule ^calendar/([^/]*)$ /calendar-site.php?year=$1&month=$2 [L]
RewriteRule ^([^/]*)/([^/]*)$ /calendar-site.php?year=$1&month=$2 [L]
The first one creates a 404 page and the second one cannot get the values from the url + it mess up the stylesheet.
Hope you guys can help me out here :D
Thanks - Jesper
You were close, but in your first try you only included one matching group for the year and not one for the month. Include the character class twice to match the year which is captured to $1 and again for the month captured in $2. Use RewriteBase to set the root for your redirect. Note that the "month" value will be in the same case as in the URL.
RewriteEngine on
RewriteBase /
RewriteRule ^calendar/([^/]*)/([^/]*)$ /calendar/calendar-site.php?year=$1&month=$2 [L]
Test using http://htaccess.madewithlove.be/
input url
http://mydomain.com/calendar/2013/november
output url
http://mydomain.com/calendar/calendar-site.php
debugging info
1 RewriteBase /
2 RewriteRule ^calendar/([^/]*)/([^/]*)$ /calendar/calendar-site.php?year=$1&month=$2 [L]
This rule was met, the new url is http://mydomain.com/calendar/calendar-site.php
The tests are stopped because the L in your RewriteRule options

Rewrite url which redirects to page on webserver

I am trying to get a page with a query string to redirect to a nicer looking url then get that url and transfer it back to the original query string but without redirecting (i.e. without changing the url)
At the moment I am getting a redirect loop (for obvious reasons) but I was hoping for a way to stop this.
This is my code in my htaccess file
#rewrite search querystring
#/search/'apartment'/2_bedrooms/price_0-500000/town_W4/development_18,SW5/
RewriteRule ^search/([^/]+)/([^/]+)_bedrooms/price_([^/]+)-([^/]+)/town_([^/]+)/development_([^/]+) /search.php?propertytype=$1&bedrooms=$2&minprice=$3&maxprice=$4&location=$5&development=$6 [NC]
RewriteCond %{QUERY_STRING} propertytype=([^/]+)&bedrooms=([^/]+)&minprice=([^/]+)&maxprice=([^/]+)&location=([^/]+)&development=([^/]+)
/search/$1/$2_bedrooms/price_$3-$4/town_$5/development_$6 [R,L]
RewriteRule ^(.*)$ /search/%1/%2_bedrooms/price_%3-%4/town_%5/development_%6? [R,L]
So what it is meant to do is:
user has been taken to:
http://www.domain.com/search/?propertytype=dev&bedrooms=2&minprice=0&maxprice=10000000&location=W1&development=W1
This page is the actual page on the server where the data is coming from, however I want the user to see.
http://www.domain.com/search/dev/2_bedrooms/price_0-10000000/town_W1/development_W1/
Is it possible to do this without a redirect loop.
Thanks for your help
EDIT I'm thinking it could be done with the rewrite flags but I'm not sure, I'm quite new to the Rewrite Engine
Edited:
Here is a complete (and working) solution for you:
RewriteEngine On
# User gets here:
# http://localhost/search/?propertytype=dev&bedrooms=2&minprice=0&maxprice=10000000&location=W1&development=W1
# He is explicit redirected to here:
# http://localhost/search/dev/2_bedrooms/price_0-10000000/town_W1/development_W1/
# Internally, apache calls this:
# http://localhost/search.php?propertytype=dev&bedrooms=2&minprice=0&maxprice=10000000&location=W1&development=W1
RewriteRule ^search/([^/]+)/([^/]+)_bedrooms/price_([^/]+)-([^/]+)/town_([^/]+)/development_([^/]+) search.php?propertytype=$1&bedrooms=$2&minprice=$3&maxprice=$4&location=$5&development=$6 [NC,PT]
RewriteCond %{QUERY_STRING} propertytype=([^/]+)&bedrooms=([^/]+)&minprice=([^/]+)&maxprice=([^/]+)&location=([^/]+)&development=([^/]+)
RewriteRule ^search/(.*)$ /search/%1/%2_bedrooms/price_%3-%4/town_%5/development_%6/? [R,L]
It assumes you put .htaccess in server root and that there is a file search.php in root too.
Original:
I think you can use PT and QSA Rewrite Rule flags (http://httpd.apache.org/docs/current/rewrite/flags.html) in your first rule
Use PT for server-side redirection (it will not change the URL for the user/browser, but will for your server-side scripts)
Use QSA if you wanna carry the query while doing this redirection
You can redirect all requests that don't target an existing file to a specific php-script, for example:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?url=$1 [PT,QSA]

Apache mod_rewrite module issue

I have the following code in my .htaccess.
RewriteEngine On
RewriteRule ^/(\w+)/?$ /?user=$1
I'm trying to rewrite
http://domain.com/?user=username into http://domain.com/username. Unfortunately this code doesn't rewrite anything. Please help
Note:
I checked phpinfo() and mod_rewrite is loaded.
Update
I need to get username from url like http://facebook.com/username. But this code rewrites every folder in root folder, so my /css folder become http://domain.com/css/?u=common. How to allow this code works only for http://domain.com/index.php
The mistake you are doing is the use of / in the beginning of the line ^/(\w+)/?$
rewrite rules strips off the / from the beginning of the pattern to be matched in .htaccess and directory context.
Try doing this:
RewriteEngine On
RewriteRule ^(\w+)/?$ /?user=$1
From RewriteRule Directive docs :
What is matched?
In VirtualHost context, The Pattern will initially be matched against the part of the URL after the hostname and port, and before the query string (e.g. "/app1/index.html").
In Directory and htaccess context, the Pattern will initially be matched against the filesystem path, after removing the prefix that lead the server to the current RewriteRule (e.g. "app1/index.html" or "index.html" depending on where the directives are defined).
If you wish to match against the hostname, port, or query string, use a RewriteCond with the %{HTTP_HOST}, %{SERVER_PORT}, or %{QUERY_STRING} variables respectively.
Edit: Answer updated as per OP's request:
Add this :
RewriteEngine On
#do nothig if URL is trying to access the folder CSS.
RewriteRule *css/* - [L]
#checks where the URL is a valid file/folder.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(\w+)/?$ /?user=$1
I think that you are doing it the right way round, but explained it the wrong way round!
Is the problem that you don't need the initial / as the URL passed to test doesn't include it!?
I suspect it should be RewriteRule ^(\w+)/?$ /?u=$1
Also, be careful you don't end up with a loop!

Categories