I was trying to prettify URLs for dynamically generated pages on my website, so that when a user visited the virtual URL topicview/interesting-user-friendly-text he would really be seeing, under the hood, topicview.php?topicid=123
I added the necessary code to my .htaccess file to replace the topicview/interesting-text part of the URL with topicview.php?topicname=interesting-test, but the Regex kept misfiring.
So, I changed the Regex to return the entire URL so I could see why it wasn't working with this code:
#Allow for topicview/topic-name URLs
RewriteRule (.+)$ topicview.php?topicname=$1 [L]
I then visited topicview/user-friendly-text. I'm not sure if this is unique to Network Solutions hosting, however, when I examined the topicname GET paramter, I got this string in return:
data/1/2/323/232/823238/user/999999/htdocs/topicview.php
This URL was not displayed in the topicname GET parameter, just a regular file, like index.php or topicview.php, if I just visit the URL index.php or topicview.php
Why is the URL internally represented like this to the Apache server, and how can I rewrite my mod_rewrite code to get a more user friendly virtual URL for the topicview.php?topicid=1 pages?
thanks
For the friendly URL try this in your .htaccess file
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/?topicview/([^/.*]+)/?$ topicview.php?topicname=$1 [L,QSA]
The pattern matched in a RewriteRule is normally the similar to the REQUEST_URI but the behaviour you describe suggests it is matching against the REQUEST_FILENAME or something similar which is the file path including the full document root.
This would suggest your RewriteRule is not in your .htaccess file but instead in your or rules in the Apache config files, correct?
Instead you should try getting the value you want using a RewriteCond so you can guarantee you are matching against the REQUEST_URI, for example:
RewriteCond %{REQUEST_URI} ^(.*)$
RewriteRule . topicview.php?topicname=%1 [L]
Note the %1 rather than $1 which allows you to use values captured in the RewriteCond.
Related
I need to remove a specific thing from my URL. Here I give a page name user.php and get it using $_GET['url'] then make it array using PHP explode() method.
https://www.example.com/index.php?url=user
I need to remove the index.php?url= like this,
https://www.example.com/user
Now I already use this code in .htaccess:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule index.php?url=$1 [QSA, L]
Almost everything was fine the user.php page was loaded perfectly. But when I was given a slash to my URL it stops showing CSS or other IMG directories. But when I delete the .htaccess file it works fine in this URL:
https://www.example.com/index.php?url=user/anonymous
But not works in this URL when I assign the .htaccess rules.
https://www.example.com/user/anonymous
Why my all stylesheet and other directory is not working perfectly?
RewriteRule index.php?url=$1 [QSA, L]
I think you have a couple of glaring typos(?) in your question that make this directive completely invalid... you are missing a RewriteRule pattern, so this won't actually match anything and the erroneous space in the flags argument is syntactically invalid, resulting in a 500 Internal Server Error response?!
The RewriteRule directive should be written like:
RewriteRule ^([\w/-]+)$ index.php?url=$1 [QSA,L]
^([\w/-]+)$ matches a URL-path containing any of the characters: a-z, A-Z, 0-9, _ (underscore), / (slash) and - (hyphen). I've excluded the dot, which is naturally part of real filenames.
You should also ensure that MultiViews is disabled, so that mod_negotiation doesn't rewrite the request before mod_rwrite - since your "extensionless" requests appear to map directly to filenames. eg. /user maps to /user.php. Place the following at the top of your .htaccess file:
Options -MultiViews
But when I was given a slash to my URL it stops showing CSS or other IMG directories.
This isn't a problem with .htaccess, but is caused by using relative client-side URLs to your static resources. When you request the URL /user/anonymous then the browser will resolve any relative URLs relative to /user/anonymous (not the document root - which is probably what you are expecting). If you have a relative URL to css/styles.css then the browser is naturally going to resolve this to /user/css/styles.css - which probably doesn't exist (and is likely getting rewritten to index.php - but that isn't the issue - the fact that it doesn't exist is the issue).
If you look at the network traffic (HTTP requests) in the browser, it should give you a clue as to what's going on.
You need to change your client-side URLs to use either root-relative (starting with a slash) or absolute (scheme + hostname) URLs to fix this issue.
See my answer to the following question on the Webmasters stack that explains this further:
https://webmasters.stackexchange.com/questions/86450/htaccess-rewrite-url-leads-to-missing-css
Use following code in your .htaccess file
RewriteEngine On
#main user page
RewriteRule ^user$ index.php?url=user [L]
#user detail page
RewriteRule ^user/([^/]*)$ index.php?url=$1 [L]
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!
I am using this rule to rewrite the link
RewriteEngine On
RewriteRule ^(.*)/(.*) show_cv.php?email=$1
It is working fine like if I write this url with last slash
www.mysite.com/letschat_2008#yahoo.com/ ----> index.php?email=letschat_2008#yahoo.com
But when I remove the last slash from the link www.mysite.com/letschat_2008#yahoo.com/ it shows error 404.
I wish the URL Rewrite rule would work for both with slash and without slash (/)
www.mysite.com/letschat_2008#yahoo.com/ ----> index.php?email=letschat_2008#yahoo.com
www.mysite.com/letschat_2008#yahoo.com ----> index.php?email=letschat_2008#yahoo.com
Your rules are looping, you need to make sure you are rewriting an email address, and add some conditions so that the rule doesn't get applied if it's accessing an existing resource:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([A-Za-z0-9_\-\#\.]+)/?$ /show_cv.php?email=$1 [L]
You should then be using the following rule:
RewriteRule ^(.*)/? show_cv.php?email=$1
I assume you note these rules in a .htaccess file, not in the server configuration when looking at your description ?
Rethink if you don-t want to put this into the server configuration. Apart from the usage of .htaccess files being harder to debug using rewrite rules in those files is more complex than in the server configuration. This is documented in mod_rewrites docs.
The reason for the behaviour is the different content of REQUEST_URI in both cases. Have a try checking this directly and you will see the problem. The whole part "letschat_2008#yahoo.com" is simply missing in that variable in case 2 (no "/"). To get this working you must use an additional rewriteCondition (also documented...). Something like these untested lines:
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/(.+)&
RewriteRule - show_cv.php?email=%1
(note the '%' instead of a '$' in the last line)
I've searched and found a lot of questions on this site and elsewhere that are very similar, but I've tried implementing and modifying all the suggestions I've found and none of it works. I realize this is a very basic question an I am extremely frustrated because nothing I'm trying is working.
With that having been said... I am trying to organize my content pages within kurtiskronk.com/pages/... (e.g. kurtiskronk.com/pages/about.php)
What I want to do is make it so that I can simply link to kurtiskronk.com/about ... So how do I go about stripping "pages/" and ".php"? I don't have a ton of content pages, so it's not a big deal if I have to specify for each page, though something dynamic would be handy.
NOTES: I am using Rackspace Cloud hosting, and WordPress is installed in /blog. My phpinfo() can be seen at http://kurtiskronk.com/pages/phpinfo.php
This is my existing .htaccess file (in the root)
php_value register_globals "on"
Options +FollowSymLinks
RewriteEngine On
#301 redirect to domain without 'www.'
RewriteCond %{HTTP_HOST} ^www\.kurtiskronk\.com$ [NC]
RewriteRule ^(.*)$ http://kurtiskronk.com/$1 [R=301,NC]
RewriteBase /
RewriteCond %{ENV:PHP_DOCUMENT_ROOT}/pages/$1 -f
RewriteRule ^(.*)$ pages/$1 [L]
RewriteCond %{ENV:PHP_DOCUMENT_ROOT}/pages/$1.php -f
RewriteRule ^(.*)$ pages/$1.php [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^blog/ blog/index.php [L]
# PHP - MAIL
php_value mail.force_extra_parameters -kurtis#kurtiskronk.com
I tested and the rewrite works with the line below (/about as URL brings up file /pages/about.php), but then the homepage gives a 500 Internal Server Error:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /pages/$1.php [L]
So I'm still sort of in the same boat as before, and as a follow-up, possibly more difficult question, if you go to http://kurtiskronk.com/weddings I am using SlideShowPro (flash) w/ SSP Director (self-hosted) as the back-end for it. When it pulls up a new image, it adds the following after /weddings ... "#id=album-152&num=content-9698"
There are four sections of the portfolio
# Homepage (kurtiskronk.com) id=album-148 ($id is constant for this section)
# Weddings (/weddings) id=album-152 ($id is constant for this section)
# Portraits (/portraits) id=album-151 ($id is constant for this section)
# Commercial (/commercial) id=album-150 ($id is constant for this section)
Assuming we get kurtiskronk.com/weddings to rewrite successfully without breaking anything, how would we make the total URL something cleaner kurtiskronk.com/weddings/9698 since the $num is the only thing that will change within a given section?
Kurtis, thanks for the extra information. It's a lot easier to give a specific answer to this.
My first comment is that you need to separate out in your thinking URI space -- that is what URIs you want your users to type into their browser -- and filesystem space -- what physical files you want to map to. Some of your mappings are URI->URI and some are URI->FS
For example you want to issue a permanent redirect of www.kurtiskronk.com/* to kurtiskronk.com/*. Assuming that you only server the base and www subdomains from this tree, then this cond/rule pair should come first, so that you can assume that all other rules only refer to kurtiskronk.com.
Next, you need to review the RewiteBase documentation. .htaccess files are processed in what Apache calls a Per-Directory context and this directive tells the rewrite engine what to assume as the URI base which got to this directory and .htaccess file. From what I gather, your blog is installed in docroot/blog (in the filesystem, and that you want to get to directory by typing in http://kurtiskronk.com/blog/ but that this .htaccess file is for the root folder -- that is the base should be (this goes before the www mapping rule)
DirectorySlash On
DirectoryIndex index.php
RewriteBase /
#301 redirect to domain without 'www.'
RewriteCond %{HTTP_HOST} ^www\.kurtiskronk\.com$ [NC]
RewriteRule ^(.*)$ http://kurtiskronk.com/$1 [R=301,NC]
You can add some field dumps look for REDIRECT_* in the Server or Environment table in the phpinfo O/P to see if these are sensible. For example:
RewriteWrite ^(.*)$ - \
[E=TESTDR:%{DOCUMENT_ROOT}/pages/$1.php,E=TESTPDR:%{DOCUMENT_ROOT}/pages/$1.php]
Your next rule is that if the file exists in the subdirectory pages then use it:
RewriteCond %{DOCUMENT_ROOT}/pages/$1 -f
RewriteRule ^(.*)$ pages/$1 [NS,L]
[Note that some shared service sites don't set up DOCUMENT_ROOT properly for the rewrite engine so you may need to run a variableinfo script (<?php phpinfo(INFO_ENVIRONMENT | INFO_VARIABLES); to see if it sets up alternatives. On your site you have to use %{ENV:PHP_DOCUMENT_ROOT} instead.]
Your next rule is that if the file exists, but with the extension .php in the subdirectory pages then use it:
RewriteCond %{DOCUMENT_ROOT}/pages/$1.php -f
RewriteRule ^(.*)$ pages/$1.php [NS,L]
Now redirect any blog references to the blog subdirectory unless the URI maps to a real file (e.g. the blog stylesheets and your uploads.)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^blog/ blog/index.php [L]
A complication here is that WP may be using a poorly documented Apache feature call Path Info that is a script can act as a pseudo directory so http://kurtiskronk.com/blog/tag/downtown/ is redirected to docroot/blog/index.php/tag/downtown/ which is then executed by `docroot/blog/index.php using /tag/downtown/ as the PATH_INFO. But this is one for Wordpress experts to comment on. If this last rule doesn't work then try:
RewriteRule ^blog/(.*) blog/index.php/$1 [L]
PS. I like your site. I wish I was that young again :(
Postscript
When you say "it doesn't work", what doesn't with this .htaccess?
http://kurtiskronk.com/phpinfo,
http://kurtiskronk.com/phpinfo.php,
http://kurtiskronk.comblog/tag/downtown/
It's just that these rules work for these tests (with domain swapped) on mine. (One way is to move or copy the above variableinfo.php to the various subdirectories. If necessary temporarily rename the index.php to index.php.keep, say, and copy the variableinfo.php to the index.php file. You can now enter the various URI test patterns and see what is happening. Look for the REDIRECT_* fields in the phpinfo output, and the SCRIPT_NAME will tell you which is being executed. You can add more {E=...] flags to examine the various pattern results. (Remember that these only get assigned if the rule is a match.
Lastly note the changes above especially the additional NS flags. For some reason mod_rewrite was going directly into a subquery which was resulting in redirect: being dumped into the file pattern. I've had a look at the Apache code and this is a internal botch to flag that further redirection needs to take place (which then replaces this or backs out). However this open bug indicates that this backout can be missed in sub-queries and maybe that's what is happening here. Certainly adding the NS flas cured the problem on my test environment.
PS. Note the added explicit DirectoryIndex directive and also that whilst http://kurtiskronk.com will run the root index.php, the explicit /index.php version will run the one in pages, because that's what your rules say.
Here is a simple solution. You can use it apache conf file(s) or in .htaccess (easier to set up when you're trying).
mod_rewrite has to be enabled.
For example, use .htaccess in your DocumentRoot with:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /pages/$1.php [L]
It will redirect /about to /pages/about.php, and any other page.
The "RewriteCond" part is to authorize access to an existing file (eg: if you had an "about" file at the root of your site, then it will be served, instead of redirecting to /pages/about.php).
Options +FollowSymLinks
RewriteEngine On
RewriteRule /([0-9]+)$ /pages/$1.php [L]
Put something like this in your .htaccess file. I guess that is what you want.
Juest a redirect from a simple url to a longer url.
What is the best way to create user vanity URLs under a LAMP configuration?
For example, a user profile page could be accessed as follows:
http://www.website.com/profile.php?id=1
Now, if a user enters a "vanity URL" for their profile I would want the the vanity URL to load the page above.
For example, if a user selects "i.am.a.user" as their vanity URL and their user id in the database is 1 then http://www.website.com/profile.php?id=1 would be accessible by that URL and http://www.website.com/i.am.a.user .
I'm aware of mod rewrites in .htaccess but not sure how that would work here.
As I mentioned my site is in PHP, MySQL, Linux and Apache.
Thanks.
Say your other pages had specific URLs that you could check against, the following should help.
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([a-zA-Z0-9-_]*)$ /profile.php?user=$1 [L]
This helps to maintain current URLs, while allowing for the user shortcut URLs. Also, the RewriteRule will only match URLs that don't contain a /, which will help protect against non-intended redirects. So,
/i-am-a-user -> MATCHES
/i_am_a_user -> MATCHES
/i-!am-a-user -> NOT MATCHED
/i.am.a.user -> NOT MATCHED
/i.am.a.user/ -> NOT MATCHED
/some/page/ -> NOT MATCHED
/doesnotexist.php -> NOT MATCHED
/doesnotexist.html -> NOT MATCHED
Hope that helps.
EDIT
I've updated the rules above so that actual files/directories aren't redirected as well as making sure that any .php or .html file is not sent to profile.php either.
Rewrite for site.com/user/USERNAME:
In your root web directory, place a .htaccess file:
RewriteEngine on
RewriteRule ^user/(.+)$ profile.php?name=$1 [L]
This routes all requests that starts with "user" to profile.php and pass the URI to $_GET['name']. This method is preferred if you have a lot of files / directories / other rewrites.
Rewrite for site.com/USERNAME:
RewriteEngine on
# if directory or file exists, ignore
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)$ profile.php?name=$1 [L]
This routes to profile.php ONLY if the requesting file or directory does not exists, AND when the request URI is not empty (ie, www.site.com)
PHP backend
Now in profile.php, you can have something like this:
if (!empty($_GET['name'])
$user = ... // get user by username
else
$user = ... // get user by id
First setup your .htaccess file to send all requests for files and directories that don't exist to a single php file:
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) router.php [NC,L]
Then inside your router.php, look at $_SERVER['REQUEST_URI'] to get the username that you can then use in your query to get the data about the user.
This assumes that all URLs that are not user profile pages exist as physical files on your server.
If that's not the case, you can do some logic in router.php to decide what to do on each request. Do a google search for url routing in php and you'll get plenty of examples.
Well, you could solve this using an apache RewriteMap as well of course. The RewriteMap can be a plain text file (that you update regularly based on what your users enter), or alternatively you could point it to a script (Perl, PHP, whatever suits you) to do the rewriting for you.
For a quick summary on how to set this up using PHP refer to Using a MySQL database to control mod_rewrite via PHP.