so i read stuff about how apache's mod_rewrite does the trick but it seems to be too vague for beginners like me.
lets say i wanted to mask site.com/userpage.php into site.com/ or site.com/userpage
or even removing the get requests..
from site.com/userpage.php?query=yes into site.com/userpage.php or site.com/userpage
how can i do that by using htaccess or even other methods?
thanks guys
First, remember to put this line in your .htaccess before any rewrites:
RewriteEngine on
If you want site.com/something to display site.com/something.php if it exists without changing the URL, do this:
RewriteCond %{REQUEST_URI}.php -f
RewriteRule .* %{REQUEST_URI}.php
That will display a [file you requested].php if it exists while still showing the same URL you entered. If the php file doesn't exist, it will still give you a 404 as it should. (That's what the -f is for.)
There is no way to hide the GET requests completely. You can get rid of the GET requests, but then they won't be available to your script either and there's no point. You can, however, make it look nicer. For example, if you want site.com/userpage/item/30 to display the content of site.com/userpage.php?item=30, you can do something like this:
RewriteRule ^/userpage/item/(.*)$ userpage.php?item=$1
You could also make it work with any GET value with a rule like this:
RewriteRule ^/userpage/(.*)/(.*)$ userpage.php?$1=$2
With that in effect, you could access site.com/userpage.php?query=yes with site.com/userpage/query/yes instead. That's pretty much the best you can do; GET values have to come from the URL somehow, so if you want your inputs completely hidden you'll have to use POST instead.
If you don't want to append the GET requests, why not use POST?
Also, you can use MultiViews to allow /userpage.php to be accessed as /userpage.
Options Indexes FollowSymLinks Includes MultiViews
The way MultiViews works it will check for a directory named userpage, and if it finds none, then it will go to the file, just a heads up in case you had a directory named userpage as well.
Related
I'm just new to .htacces
I want:
example.com/page.php?page=how-to-learn
changed to:
example.com/how-to-learn
I google'd some and tried but no change url.
That's not how .htaccess work : it won't change your links to display the corrected version, but it looks for a match in the expressions you'll write into it to rewrite the correct parameters.
For example, in your code, your .htaccess sould look something like this :
RewriteEngine On
RewriteRule ^([a-z-]+)$ page.php?page=$1 [QSA,L]
If you write example.com/how-to-learn in your browser, you'll be able to see the content of example.com/page.php?page=how-to-learn.
I advise you to be VERY careful though : as the expression is VERY permissive, you'll have to check in the page.php file that the file if legitimately allowed to be loaded.
I'm doing my first steps with url-rewriting and can't get the following to work:
In my application, a skin can be loaded by applying query parameter ?skin=some_id to any page in the application. I want to change:
http://www.mysite.com/anypage.html?skin=123
into:
http://www.mysite.com/123/anypage.html
but I cannot get it to work.
This is what I currently have in my httpd.conf:
<IfModule mod_rewrite.c>
RRewriteRule (.*)/(.*)?app=(.*)$ %1/%3/%2 [NC,R=301,L]
</IfModule>
Questions:
This isn't working, so I would like to know what I'm doing wrong?
Also with the URL in effect, what is the URL the user enters? http://www.mysite.com/123/anypage.html which "maps" to http://www.mysite.com/anypage.html?skin=123?
And if I want to access the query parameter, do I have to extract it from the actual url (?skin=...) or from the rewritten URL?
Thanks for helping out!
EDIT:
So I have it sort of working doing it like this (helpful tester here):
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{QUERY_STRING} skin=(\w+)
RewriteRule ^.*\.html /%1? [R=301]
</IfModule>
This will redirect:
www.some.com/index.html?skin=xyz => www.some.com/xyz
Not quite there yet.
I'd recommend going about skinning your application differently. The way you have it now will create duplicate content issues with search engines because they will see the same content for each page on your site for every skin you have.
That is to say, yoursite.com/dark/about.html would be identical content to yoursite.com/spring/about.html so search engines may have a hard time deciding which version to use. In addition, it seems like it will create extra work for linking to other pages on your site since you will have to create your links programmatically to use the proper path and skin.
I would just have a URL for activating a skin and store their preference in a cookie or in a session and skin the site based on the cookie/session value and only maintain one set of URLs.
Unless you really want the skin to be in the URL, I would shy away from using the URL or query string to indicate which skin to use. Instead have it be a preference attached to an account or stored in a cookie.
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!