I'm using CodeIgniter for a web application, and now I have an urgent question: I just discovered that urls are case sensitive in Linux based servers, and I have just moved a site from Windows to Linux. This means links to the site don't work anymore where there are now all lower-case urls, which were not before.
Googling I found that you should be able to do something like this in the .htaccess file:
RewriteMap lc int:tolower
RewriteCond %{REQUEST_URI} [A-Z]
RewriteRule (.*) ${lc:$1} [R=301,L]
But I tried that and it was not good at all...! Suddenly I got a big ugly error page staring at me instead, saying that there must be something wrong with the Tomcat server or something like that. Needless to say I removed those lines immediately!
But why didn't it work then, and what should I do instead?
Any help would be greatly appreciated.
Code igniter supports regular expressions - if you'd like to be explicit in the definition of your routes, define them in this fashion to be case insensitive:
$route['(?i)(about\/contact)'] = 'about/contact';
If case insensitive routes are required, do below changes to URI.php
Location of File: system/core/URI.php
Find $this->_parse_request_uri() and replace it with strtolower($this->_parse_request_uri())
Actually found out that it was quite easy, surprised that no one answered this (perhaps it isn't the correct way, but I would think so...):
I just added some routes in the routes.php file in the config folder:
$route['About/Contact'] = "about/contact";
And so on...
Related
I have a website:
www.mydomain.com/subfolder/subfolder/index.php
How could always hide the directory names from the url. I mean always hide the 2 subfolders' names from the url as the page changes.
Example:
These urls:
www.mydomain.com/subfolder/subfolder/index.php
www.mydomain.com/subfolder/subfolder/about.php
www.mydomain.com/subfolder/subfolder/contact.php
...
Becomes:
www.mydomain.com/index
www.mydomain.com/about
www.mydomain.com/contact
...
I want to use the last mentioned urls for requesting these pages, too, without typing a horrible long url.
you can find some good hints when you will look for mod_rewrite or mod rewrite in htaccess.
If you have access to the Rewrite engine, you can use a simple rewriting pattern similar to this:
RewriteRule ^/(.*)$ /subfolder/subfolder/$1.php
It seems a site is linking to mine in a bad way.
From google webmaster tools I see some 404 errors
domain.com/file.php?id=1 (404) Not found (Date)
This url works ok but because of browser page decoding, the real (404) url is
domain.com/file.php%3Fid%3D1 (this is what my browser displays in the url input when I click on google url)
My first try was
RewriteRule ^(.*)\%3F(.*)$ $1?$2 [R=301, L]
to change %3F to '?' but it does not work. It is confusing what is real and what is en/decoded.
Thanks
Hmm, try this:
RewriteRule ^(.*\%3F.*)\%26([^%]*)(\%3D)?(.*)$ $1&$2=$4 [N]
RewriteRule ^(.*)\%3F([^%]*)(\%3D)?(.*)$ $1?$2=$4 [R=301,L]
EDIT: I see you already tested for %3F... if that didn`t work, then something else might be up.
It is not an elegant solution, but after months, it is the only way I found.
Regular case
domain.tld/dir/file.php?id=UID&qty=NUM&... (from old site structure)
is rewritten as
domain.tld/newfile.php?id=UID&qty=NUM&... [R=301,L]
So, for requests like
domain.tld/dir/file.php%3Fid%3DUID%26qty=NUM%26... (from old site structure)
I perform
RewriteRule ^dir/file\.php(.*)$ script.php?qs=$1 [R,L]
This MUST be AFTER all directives that involves dir/file.php
Then I can handle the query string $_GET['qs'] in script.php
It may not apply to other situations that would enter into a loop or undesired results.
use [NE] flag in your RewriteRule
Thanks to the people that've helped me so far with this, I'm ready for the last step, I think.
I've got my URLs looking like this.
/brochure.php?cat_path=35&name=concrete-intermediate-posts
This is great and finally I just need to know how to turn that URL into this desired URL:
/brochure/35/concrete-intermediate-posts
Just like the Stack Overflow format.
Could anyone help me with the correct .htaccess rule?
Also, if I have other get variables in other sections, will this re-write harm them? (they use different variable names)
Thanks
With mod_rewrite you will rather do the opposite: rewrite a URL path like /brochure/35/concrete-intermediate-posts internally to /brochure.php?cat_path=35&name=concrete-intermediate-posts:
RewriteRule ^([^/]+)/(\d+)/([^/]+)$ $1.php?cat_path=$2&name=$3 [L,QSA]
The other side, using a URL path like /brochure/35/concrete-intermediate-posts instead of /brochure.php?cat_path=35&name=concrete-intermediate-posts in the HTML documents, would be done with PHP.
I Hope you mean something like this:
RewriteEngine On
RewriteBase /
RewriteRule ^brochure/([0-9]+)/([-a-zA-Z0-9]+)$ /brochure.php?cat_path=$1&name=$2 [L]
I need to grab some of my website's old URLs and do a 301 redirect to the new ones, since they are already indexed and we don't want to loose relevance after the change. The old URL is in fact very ugly and for some reason everything I try to do to rewrite it does not work. Here it is:
http://www.mywebsite.com/ExibeCurso.asp?Comando=TreinamentoGeral&codCurso=136&Titulo=Como%20Estruturar%20um%20Sistema%20Gerencial%20de%20Controles%20Organizacionais,13
Basically, I need to translate it into something like:
http://www.mywebsite.com/curso/136
From the old URL I need to check if the user typed "ExibeCurso.asp"; then I know I must send him here: /curso. I must also grab the integer that was in the querystring parameter "codCurso" (136). What is the regular expression I must use for this. I am using ISAPI_Rewrite 3, which basically implements htaccess on IIS, so there should be no difference in terms of syntax. Thanks.
Try this rule:
RewriteCond %{QUERY_STRING} ^([^&]*&)*codCurso=([0-9]+)(&.*)?$
RewriteRule ^/ExibeCurso\.asp$ /curso/%2? [L,R=301]
But I’m not sure whether ISAPI Rewrite requires the pattern to begin with a slash.
Off the top of my head, something like this should work:
RewriteRule ^ExibeCurso.asp(.*)$ http://www.mywebsite.com/curso/$1 [L,R=301]
That would at least send the traffic to /curso/ with all parameters attached. Maybe it's best to process it from there.
It's of course nice to give users friendly URLs for their content on your site. But how best to do that? There are a lot of advantages to something like foo.com/users/alice, most importantly that you aren't cluttering up your root namespace. But I think simplicity for users trumps all that. A lot of big sites seem to agree (friendfeed, delicious, and flickr come to mind) and this question is about how to accomplish that on the server side.
Let's assume the real URL for alice is foo.com/userpage?user=alice and that if someone tries to surf to a nonexistent user page (let's say foo.com/bob) they should reach foo.com/createnew?user=bob.
The user of course should never see the ugly "real" URLs above, just foo.com/alice or foo.com/bob. And note that the root namespace is shared. For example, foo.com/help should not get translated to foo.com/userpage?user=help.
Presumably I'm asking for some simple mod_rewrite rules, but perhaps there's some completely different approach to this that I'm not thinking of. In any case, I thought it would be good to record a definitive or "best practice" solution to this common question.
PS: Feel free to comment on the merits of other alternatives like alice.foo.com or users.foo.com/alice.
PPS: I think I've seen this issue debated in other questions but it seems to be tricky to search for. Pointers welcome! As well as additional keywords to make this more searchable, of course. Keywords: userspace, global namespace, URL namespace.
I would say it depends on how user centred your site is.
Sites like myspace are http://www.myspace.com/jim/ because the site entirely revolves around the user.
A blog or news site, however, where you can register but it isn't important or mandatory could benefit from
http://www.news.com.au/users/jim/
Do you think if you're doing a website with users you could benefit from the MVC design pattern, or at least a popular MVC framework which uses a router to direct URIs?
If that URI came through a Router, and then was sent to the UsersController, you could decide to either show the user's profile, or direct them to create that user. You would not need to mess around with mod_rewrite except to make one rule that directs all requests to non existent files to index.php (or whatever the default of your server side language is)
If you do want to use mod_rewrite, try these rules
RewriteEngine On
RewriteCond %{REQUEST_URI} !(home|contact|about) [NC] // this line may be incorrect
RewriteRule ^/users/([^/]+)/?$ userpage?user=$1 [NC,L]
Please note the leading Carat as suggested by Gumbo, so it only matches /users/ of the TLD only.
That will match anything like foo.com/users/bob with an optional trailing slash. It is case insensitive and will be the last rule applied.
If the request comes in and the $_GET['user'] does not exist in your DB, you could try something like this
$user = $_GET['user'];
if (!user_exists($user)) {
header('Location: createnew?user=' . urlencode($user));
exit();
}
Then on the createnew page, simply do something like this
<input type="text" name="username" value="<?php echo htmlspecialchars(urldecode($_GET['user'])); ?>" />
That will fill in the username automatically with the username they tried to access a profile with.
If you'd like to know more about PHP and MVC, try a Google search or ask a question here on Stack Overflow.
The following rules rewrite a URL of the form foo.com/bar to foo.com/userpage?user=bar conditional on bar not already being a file or directory on the server. Put the following in .htaccess:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/?$ userpage?user=$1 [NC,L]
</IfModule>
As in Alex's answer, the userpage script should redirect to createnew if the user doesn't exist:
$user = $_GET['user'];
if (!user_exists($user)) {
header('Location: createnew?user=' . urlencode($user));
}
(As Knuth says, beware of bugs in the above code -- I have only proved it correct, not tried it. I'll update this answer when I've actually confirmed it works.) PS: CONFIRMED!