I am having difficulty with code igniter routing.
http://www.mysite.com goes to the right controller and does the right thing. However, http://www.mysite.com/?ref=p&t2=455 causes a 404 error. Also http://www.mysite.com/mycontroller/mymethod/?ref=p&t2=455 works fine.
I changed the uri_protocol in the config.php file and tried different values. Auto seems to work the best.
My theory is that code igniter is using the query parameters to do the routing. The problem is that these query parameter have nothing to do with routing.
How do I tell code igniter to ignore query parameters for the default controller?
Note, I followed the instructions online to remove the index.php from the URL. I dont think its causing a problem, but here is my .htaccess file just in case:
RewriteEngine On
RewriteBase /~trifecta/prod/
#Removes access to the system folder by users.
#Additionally this will allow you to create a System.php controller,
#previously this would not have been possible.
#'system' can be replaced if you have renamed your system folder.
RewriteCond %{REQUEST_URI} ^system.*
RewriteRule ^(.*)$ /index.php?/$1 [L]
#Checks to see if the user is attempting to access a valid file,
#such as an image or css document, if this isn't true it sends the
#request to index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
#This last condition enables access to the images and css folders, and the robots.txt file
#Submitted by Michael Radlmaier (mradlmaier)
RewriteCond $1 !^(index\.php|images|robots\.txt|css)
RewriteRule ^(.*)$ index.php?/$1 [L]
With that rewrite rule RewriteRule ^(.*)$ /index.php?/$1, here are some examples of rewrites that are occuring:
http://www.mysite.com =>
http://www.mysite.com/index.php?/ (actually, this might not be being rewritten at all)
http://www.mysite.com/mycontroller/mymethod/?ref=p&t2=455 =>
http://www.mysite.com/index.php?/mycontroller/mymethod/?ref=p&t2=455
http://www.mysite.com/?ref=p&ts=455 =>
http://www.mysite.com/index.php?/?ref=p&t2=455
The first one will work whether it is being rewritten or not. CodeIgniter is processing either an empty query string (which is easy) or a query string of simply "/".
The second one (which also works) is being rewritten, but CodeIgniter is able to process its query string, which is /mycontroller/mymethod/?ref=p&t2=455. CI turns that into an array of segments as
[0] => mycontroller
[1] => mymethod
[2] => ?ref=p&t2=455
Array index 2 ultimately gets ignored by anything you're doing.
The third one (which does not work is being rewritten, and CodeIgniter can't process its query string at all. Its query string is rewritten to: /?ref=p&t2=455. That makes for an array of segments that looks like this:
[0] => ?ref=p&t2=455
which doesn't match any controller on your site.
Probably, you'll fix the whole thing by modifying the RewriteRule from
RewriteRule ^(.*)$ /index.php?/$1 to
RewriteRule ^(.*)$ /index.php/$1
at which point you'd probably want to change the uri_protocol config back to PATH_INFO.
It seems to be a limitation in the way CodeIgniter is designed, not as a result of your routing and/or .htaccess. Someone filed a bug report here. However, instead of using this and adding your mymethod code into your index method of your default controller, you could use the _remap() function like so:
function _remap($method)
{
if ($method == 'index' && count($_GET) > 0)
{
$this->mymethod();
}
else
{
$this->index();
}
}
With the following configuration it works fine for me. http://www.site.com/?x=y gets routed to the index method of the default controller.
.htaccess
RewriteEngine on
RewriteCond $1 !^(index\.php)
RewriteRule ^(.*)$ index.php/$1 [L]
system/application/config/config.php
$config['base_url'] = "http://www.site.com/";
$config['index_page'] = "";
$config['uri_protocol'] = "PATH_INFO";
$config['permitted_uri_chars'] = 'a-z 0-9~%.:_\-?';
Remember to add ? to the list of permitted characters in the URL. Perhaps this is causing a problem. I just tried this setup with a clean installation of CodeIgniter and it worked fine. These were the only changes I needed to do.
Here is how I got around it:
1. I have a standard rewrite in .htaccess:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?/$1 [QSA,L]
This is likely unrelated but...
in index.php the file outside the application folder I added:
$pattern = "/\?.*$/";
$replacement = '';
$_SERVER['REQUEST_URI'] =preg_replace($pattern, $replacement, $_SERVER['REQUEST_URI']);
this stops codeigniter from trying to use the querystring in the request. Now did you actually need the $_GET variables? They need to be parsed out of $_SERVER['REDIRECT_QUERY_STRING'] which will be set if you used mod_rewrite as above.
Try the CodeIgniter Super .htaccess file
Related
This seems so basic, and there's a plethora of questions regarding .htaccess online, but after two days of research, I still can't make mine work the way I want.
What I want is:
Force https on all requests
Always use the "www" version of the url.
Work on multiple domains (but not redirect them all to a master domain). All my domains point to the same folder (so they'd use the same codebase), and in its root is the .htaccess file.
Remove the "index.php" part of the url, to make it human and SEO friendly.
This is what I have so far:
Start with the basic .htaccess code for CodeIgniter, as shown in the userguide:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1
Originally, the last line had the [L] flag, but I omitted it, so it will continue to the following rules.
(Am I correct in assuming that it takes the url output in the previous RewriteRule, and perform the following matches on it?)
# for non www urls, add www and force https:
RewriteCond %{HTTP_HOST}(.*) !^www\. [NC]
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1 [R,L]
# for www urls, just force https:
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R,L]
The above code is achieving tasks 1-3 of my list above, but the index.php is still showing in the address bar.
How do I remove it?
Well, I (partially) gave up on .htaccess, and solved my problem in a different way:
I'm now using CodeIgniter hook to deal with forcing https, and leave htaccess to deal only with forcing www and removing index.php
So I removed the last line (RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R,L]), and added an ssl hook to my application, and all is working now.
The hook function, in case anyone is interested, is this:
function force_ssl()
{
if ($_SERVER['HTTP_HOST']!='localhost' && $_SERVER['HTTP_HOST']!='10.0.2.2')
{
$CI =& get_instance();
$CI->config->config['base_url'] = str_replace('http://', 'https://', $CI->config->config['base_url']);
if ($_SERVER['SERVER_PORT'] != 443) redirect($CI->uri->uri_string());
}
}
In my .htacess of my domain, I must point subdomain to the 1rst GET parameter of the domain. The subdomain represents the language (for example en., fr, etc...).
In order to achieve this aim, here the rewrite code in the .htaccess :
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^(.*)\.example\.com$ [NC]
RewriteRule ^(.*)$ $1?lang=%1 [NC,L]
I create a directory named test. This directory contains just index.html file.
So when you type in the url bar of a browser en.example.com/test/,
the rewrite code works.
But if you type en.example.com/test without the final slash, it redirects to en.example.com/test/?lang=en => it's a problem.
So have you an idea to correct that ?
Thank you in advance, cordially.
When specifying xx.example.com/test/, an internal redirect
occurs to xx.example.com/test/?lang=xx. The client never sees the ?lang=xx.
However, when specifying xx.example.com/test, where test is a directory,
mod_dir steps in and rewrites the URL to xx.example.com/test/, but in
such a way that the rewrite rule for the ?lang=xx redirect becomes public,
having the client see xx.example.com/test/?lang=xx as the URL - which is unwanted.
In order to keep the '?lang=' redirect local (hidden from the client)
place this in the .htaccess, BEFORE the original rewrite rules:
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.+[^/])$ $1/ [R,L]
The condition checks whether the requested filename is a directory,
and the rule forces a client-side redirect [R], so that a client requesting xx.example.com/test will be redirected to xx.example.com/test/.
The key however is the [L], which makes this rule the Last, preventing the following rules from executing. Without this L flag, the entire redirect from xx.example.com/test to xx.example.com/test/?lang=xx becomes public.
After the client is forcefully redirected to the proper URL with a terminating /, the rewrite rules doing the internal redirect adding the lang GET parameter are executed as normal.
Here's the entire .htaccess:
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.+[^/])$ $1/ [R,L]
RewriteCond %{HTTP_HOST} ^(.*)\.example\.com$ [NC]
RewriteRule ^(.*)$ $1?lang=%1 [NC,L]
There is however another way to achieve this without using Apache config and internal redirect, and that is to examine $_SERVER['SERVER_NAME']:
<?php
list( $lang ) = explode('.', $_REQUEST['SERVER_NAME'] );
On my CodeIgniter site, I would like to add a specific rewrite rule, so that this url
http://www.exemple.com/cache.manifest
would rewrite to
http://www.exemple.com/controller/manifest
(because Safari 7 seems to only accept .manifest files for ApplicationCache)
So I try to add this line to my htaccess
RewriteRule ^cache.manifest$ controller/manifest
I added it before the other rewrite rules :
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^cache.manifest$ controller/manifest
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php/$1 [L]
</IfModule>
But it returns a 404. If I change the line to
RewriteRule ^cache.manifest$ test.html
it works. So the first part on my rule is correct.
If I try to access directly to www.example.com/controller/manifest, it works to, so my url is correct.
I tried also
RewriteRule ^cache.manifest$ index.php/controller/manifest [L]
But it doesn't work either…
Any clue ?
Thanks a lot
I tried some tests on my local server and I think the following might work:
RewriteRule ^cache.manifest$ /index.php/controller/manifest [R,L]
I am not entirely sure if you need the leading "/" or "/index.php", so you
may need to experiment.
You need the [R] flag to force a redirect. In this situation, you want Apache
to look for the string cache.manifest in the URL, and then go to the CI page
controller/manifest.
It appears that you need to explicitly set the redirect.
Please let me know if this works. Good luck!
initally, i'm sorry about my question-title, but really nothing better came into my mind....
i've got a .htaccess file that does the "usual" rewriting:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^(.+)$ index.php?url=$1 [QSA,L]
this gives me the possibility of have this url for example (i'm working with xampp):
localhost/<project>/en/products/electronic/television/
so this url is in the $_GET['url'] variable and i can use it (as an array) to load the controller in my HMVC pattern.
and, to not have to enter the language ("en" in the example above), i've implemented a function that inserts automatically "en". basically that means the following url gives the same controller, and respectively the same output.
localhost/<project>/products/electronic/television/
but now i wonder, that my javascript files (jquery & co), that are lying in the folder
<project>/lib/js/query/jquery.min.js
can be simply required like this:
<script type="text/javascript" src="/<project>/lib/js/jquery/jquery.js"></script>
i expected that the requested path would eventually be something like this (as i add the language in the $_GET['url'] variable and it would try to load a controller and fails...
src="/<project>/en/lib/js/jquery/jquery.js"
well, in that case i would be glad that it works this way, but it brought me to the idea to try this:
$(document).ready(function() {
alert("this is a test");
$.get("/<project>/<config-dir>/<config-file>", function(data) {
alert(data);
});
});
voila, it outputs the config file.
i think that the behavior will be the same on a productive server, but then just without the "/" nodes in the paths.
how can i prevent this, without moving the config-file from document root?
basically, i've ensured that XSS-attacks won't (almost) be unsuccessful. the "almost" just because there is no 100% safety.
i hope i expressed myself well :)
thanks for the help/suggestions.
well, i found out, what the problem was, why i could access the config file: the rewrite conditions. they say simply, that the following rule should became effective if the requested filename is not a directory or file or link(?).
RewriteEngine On
# RewriteCond %{REQUEST_FILENAME} !-d not a directory
# RewriteCond %{REQUEST_FILENAME} !-f not a file
# RewriteCond %{REQUEST_FILENAME} !-l not a link(?)
RewriteRule ^(.+)$ index.php?url=$1 [QSA,L]
so basically this explains, why the rewriting rule did not work on ajax-requests (it did not work on normal requests as well)
now my problem with unallowed access is solved.
to exclude some specific directories from the rewrite rule i added this rule for:
RewriteRule ^(<dirname>)($|/) - [L]
I am new to CodeIgniter. I have an XAMPP server on Windows 8. Everything is fine, but the problem is about my URL, it doesn't look friendly. It looks like localhost/ci/index.php/site/home (where ci is my root folder for CodeIgniter). I want to make the URL more clean, like localhost/ci/home, how can I do it?
My CodeIgniter version is 2.1.2.
I have done some research already, but in most of the cases it says to change the .htaccess file of CodeIgniter. But I have nothing in the .htaccess file; it's empty, except the line "Deny from all".
You can do this, in config/config.php:
$config['base_url'] = 'http://'.$_SERVER['HTTP_HOST']; //you can also leave blank this CI tend to find this by himself
$config['index_page'] = '';
And try the following .htaccess. I use it for many sites, and it satisfies me.
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php/$1 [L]
If it is not working yet, use a phpinfo(); and check if mod_rewrite is enabled. If it is not enabled, you can follow the instructions in Stack Overflow question How do you enable mod_rewrite? to enable that.
If it is not working yet and mod_rewrite is enabled yet, you can try to switch these in config/config.php:
$config['uri_protocol'] = 'AUTO'; //If not working, try one of these:
'PATH_INFO' Uses the PATH_INFO
| 'QUERY_STRING' Uses the QUERY_STRING
| 'REQUEST_URI' Uses the REQUEST_URI
| 'ORIG_PATH_INFO' Uses the ORIG_PATH_INFO
You need to replace "Deny from all" with this:
RewriteEngine on
RewriteCond $1 !^(index\.php|images|robots\.txt)
RewriteRule ^(.*)$ /index.php/$1 [L]
http://ellislab.com/codeigniter/user-guide/general/urls.html
Looking at the official documentation, CodeIgniter URLs:
You can easily remove this file by using a .htaccess file with some simple rules. Here is an example of such a file, using the "negative" method in which everything is redirected except the specified items:
RewriteEngine on<br>
RewriteCond $1 !^(index\.php|images|robots\.txt)<br>
RewriteRule ^(.*)$ /index.php/$1 [L]<br>
Also if you are using Apache place .htaccess file in your root web directory. For more information, look in Codeigniter .htaccess.