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
Related
Trying to use .htaccess rule to do the wp-login JS check on first visit by appending ?/wp-login to the url since it's interferring with Sucuri firewall when using password protection.
I've created a test subdomain to try to get the htaccess redirect to work before using it on the live site:
RewriteCond %{QUERY_STRING} ^protectedpage$
RewriteRule ^(.*)$ https://testing.no11.ee/protectedpage?/wp-login [R=302,L]
view here: testing.no11.ee/protectedpage
Unfortunately this does not add the query arg to the url. What am I doing wrong here?
Expected result when visiting page should be https://testing.no11.ee/protectedpage?/wp-login as the browser url.
Full htaccess:
# BEGIN WordPress
# The directives (lines) between "BEGIN WordPress" and "END WordPress" are
# dynamically generated, and should only be modified via WordPress filters.
# Any changes to the directives between these markers will be overwritten.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
RewriteCond %{QUERY_STRING} ^protectedpage$
RewriteRule ^(.*)$ https://testing.no11.ee/protectedpage?/wp-login [R=302,L]
</IfModule>
# END WordPress
RewriteCond %{QUERY_STRING} ^protectedpage$
RewriteRule ^(.*)$ https://testing.no11.ee/protectedpage?/wp-login [R=302,L]
This checks that the QUERY_STRING is set to protectedpage, but in your example it's the URL-path that is /protectedpage, not the query string.
You also need to first check that the query string is not already set to /wp-login, otherwise you'll get a redirect loop.
However, you've also put the code in the wrong place. Note the WordPress comment that precedes the code block - you should not manually edit this code. This directive also needs to go before the WordPress front-controller, otherwise, it's simply never going to get processed.
Try the following instead before the # BEGIN WordPress comment marker:
RewriteCond %{QUERY_STRING} !^/wp-login$
RewriteRule ^(protectedpage)/?$ /$1/?/wp-login [R=302,L]
This matches an optional trailing slash on the requested URL, but it redirects to include the trailing slash in the target URL.
(You do not need to repeat the RewriteEngine on directive.)
No need to include the scheme + hostname if you are redirecting to the same. The $1 backreference simply saves repetition and refers to the matched URL-path, ie. protectedpage (without the trailing slash) in this example.
However, this always redirects and appends /wp-login to this URL - not just the "first visit" - is that really what you require? Otherwise, you need to somehow differentiate between "first" and "subsequent" visits (by detecting a cookie perhaps?)
UPDATE: Minor addition: how would one improve this to add ?/wp-login to all urls that have the page /subpage/ as parent i.e /subpage/page-1 and /subpage/page-2 would result in /subpage/page-1?/wp-login etc? I tried using (.*) but this delets the subpage from the url...
You could do something like the following:
RewriteCond %{QUERY_STRING} !^/wp-login$
RewriteRule ^(subpage/[^/]+)/?$ /$1/?/wp-login [R=302,L]
The [^/]+ subpattern matches any character except / - so only the second path segment, excluding the optional trailing slash. This is similar to .*, but this would capture everything, including any trailing slash, so would result in a double slash in the redirected URL.
I'm trying to figure out how to rewrite urls using apache webserver and php.
The url below is the real nonrewritten url:
http://localhost:1337/rewritetest/index.php?id=12
And I want to reach it by
http://localhost:1337/rewritetest/index/12
My indexfile looks like this:
<?php
echo $_GET['id'];
?>
Is this possible? The "new" url doesn't include any parameter names so I guess I have to use an order of parameters instead but I dont know how to reach them in that case.
Below is as far I've come with my rewrite:
RewriteCond %{QUERY_STRING} id=([-a-zA-Z0-9_+]+)
RewriteRule ^/?index.php$ %1? [R=301,L]
RewriteRule ^/?([-a-zA-Z0-9_+]+)$ index.php?id=$1 [L]
Anyone have an idea of what I'm doing wrong?
it's located in the same folder as index.php
So, given the .htaccess file is located at /rewritetest/.htaccess (as opposed to the document root ie. /.htaccess) then...
RewriteRule ^/?([-a-zA-Z0-9_+]+)$ index.php?id=$1 [L]
If you request a URL of the form /rewritetest/index/12 then the above RewriteRule pattern won't actually match anything. It tries to match "index/12", but your pattern does not contain a slash so will fail. (Is the + inside the character class intentional?)
Try something like the following instead:
RewriteRule ^(index)/(\d+)$ $1.php?id=$2 [L]
This obviously specifically matches "index" in the URL. If you are always rewriting to index.php then you don't really need "index" in the URL - unless this means something different? This also assumes that the valuue of the id parameter consists only of digits.
To rewrite the more general .../<controller>/26 to .../<controller>.php?id=26 (as mentioned comments) then try something like:
RewriteRule ^([\w-]+)/(\d+)$ $1.php?id=$2 [L]
In per-directory .htaccess files the slash prefix is omitted on the URL-path that is matched by the RewriteRule pattern, so /? is not required. The above pattern also matches something for for the id, not anything. So, /index/ would not match.
If this is a new site then the "redirect" (from /index.php?id=12 back to /index/12) is not necessarily required. That's only really required if you are changing the URL structure on an existing site where old URLs already have inbound links and are indexed by search engines. In which case you could do something like the following before the internal rewrite:
RewriteBase /rewritetest/
RewriteRule %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} ^id=(\d+)
RewriteRule ^(index)\.php$ $1/%1 [R,L]
Or, for a more generic .../<controller>/26 to .../<controller>.php?id=26 (as above) then change the RewriteRule to:
RewriteRule ^([\w-]+)\.php$ $1/%1 [R,L]
The additional check against the REDIRECT_STATUS environment variable is to prevent a rewrite loop after having rewritten the URL to /index.php?id=12 earlier.
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
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]
I'm trying to convert a query string;
http://atwd/books/course?course_id=CC100&format=XML&submit=Submit
Into a segment URI;
http://atwd/books/course/CC100/XML
I'm working in CodeIgniter.
I was looking at a stackoverflow answer that said to check CodeIgniter's URL segment guide, but I don't think there's any information on how to convert a query string into a segment URI. There is, however a way to convert a segment URI into a query string, which is bringing up a load of results from Google too.
Following another stackoverflow answer, I tried this in my .htaccess file but nothing seemed to work
RewriteCond %{QUERY_STRING} ^course_id\=([^&]+)\&format\=([^&]+)$
RewriteRule ^$ /course/%1/format/%2 [R,L]
In my entire .htaccess file I have this;
<IfModule mod_rewrite.c>
RewriteEngine on
#Source: http://codeigniter.com/user_guide/general/urls.html
#Removal of index.php
RewriteCond $1 !^(index\.php|images|robots\.txt)
RewriteRule ^(.*)$ /index.php?route/$1 [L]
#Source: https://stackoverflow.com/questions/3420204/htaccess-get-url-to-uri-segments
#Format Course function requests
RewriteBase /
RewriteCond %{QUERY_STRING} ^course_id\=([^&]+)\&format\=([^&]+)$
RewriteRule ^$ /course/%1/format/%2 [R,L]
</IfModule>
This is in my root directory of Codeigniter screenshot
My code in the .htaccess file isn't working, I refresh the page and nothing happens. The code to hide the index.php is working though. Does anyone know why?
The notion of "converting URLs" from one thing to another is completely ambiguous, see the top part of this answer for an explanation of what happens to URLs when redirecting or rewriting: https://stackoverflow.com/a/11711948/851273
There's 2 things that happen, and I'm going to take a wild stab and guess that you want the 2nd thing, since you're complaining that refreshing the page doesn't do anything.
When you type http://atwd/books/course?course_id=CC100&format=XML&submit=Submit into your browser, this is the request URI that gets sent through mod_rewrite: /books/course. In your rule, you are matching against a blank URI: RewriteRule ^$ /course/%1/format/%2 [R,L]. That's the first reason your rule doesn't work. The second reason why it doesn't work is because above that, everything except images and index.php and robots.txt is being routed through index.php. So even if you were matching against the right URI, it gets routed before your rule even gets to do anything.
You need to correct the pattern in your rule to match the URI that you expect to redirect, and you need to place this rule before the routing rule that you have. So everything should look roughly like this:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /
RewriteCond %{QUERY_STRING} ^course_id\=([^&]+)\&format\=([^&]+)$
RewriteRule ^/?books/course$ /course/%1/format/%2 [R,L]
#Source: http://codeigniter.com/user_guide/general/urls.html
#Removal of index.php
RewriteCond $1 !^(index\.php|images|robots\.txt)
RewriteRule ^(.*)$ /index.php?route/$1 [L]
</IfModule>
You'll need to tweak the paths to make sure they match what you are actually looking for.
To both redirect the browser and internally rewrite back to your original URL, you need to do something different.
First, you need to make sure all of your links look like this: /course/CC100/format/XML. Change your CMS or static HTML so all the links show up that way.
Then, you need to change the rules around (all before your codeigniter routing rule) to be something liek this:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /
# redirect browser to a URI without the query string
RewriteCond %{THE_REQUEST} ^(GET|HEAD)\ /books/course/?\?course_id=([^&]+)&format=([^&]+)
RewriteRule ^/?books/course$ /course/%2/format/%3? [R,L]
# internally rewrite query string-less request back to one with query strings
RewriteRule ^/?course/([^/]+)/format/([^/]+)$ /books/course?course_id=$1&format=$2&submit=Submit [L]
#Source: http://codeigniter.com/user_guide/general/urls.html
#Removal of index.php
RewriteCond $1 !^(index\.php|images|robots\.txt)
RewriteRule ^(.*)$ /index.php?route/$1 [L]
</IfModule>
I'm not going to address the misunderstanding already addressed pretty well in the other answer and comments, and I can't speak for CodeIgniter specifically, but having given their URL routing docs a quick skim, it seems pretty similar to most web frameworks:
You probably just want to direct all traffic (that doesn't match physical files) to the frontend web controller (index.php) and handle the URL management in CodeIgniter's routing, not a htaccess file.
To do that, your htaccess could be as simple as:
<IfModule mod_rewrite.c>
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* index.php [QSA,L]
</IfModule>
This, as I said, will redirect any traffic that doesn't match an physical file such as robots.txt or an image to your index.php.
Then, using the routing as described in the docs (http://ellislab.com/codeigniter/user-guide/general/routing.html) you can take in parameters and pass them to your controllers as you see fit, there is no need to 'convert' or 'map' anything, your URL's don't need to resolve to /?yada=yada internally, based on your routing rules CodeIgniter can work it out.
You'll need wildcard routes such as this from the docs:
$route['product/:id'] = "catalog/product_lookup";
A rough example of what yours might end up looking like would be something like:
$route['course/:id/format/:format'] = "course/something_or_other_action";
If I'm understanding you correctly, you might be over-thinking it. I have something similar in my own code.
I have a controller named Source. In that controller, I have the following method:
public function edit($source_id, $year)
{
# Code relevant to this method here
}
This produces: http://localhost/source/edit/12/2013, where 12 refers to $source_id and 2013 refers to $year. Each parameter that you add is automatically translated into its own URI segment. It required no .htaccess trickery or custom routes either.