Hide Page Extensions (Like StackOverflow) - dynamic-data

I want to hide page extensions like stackoverflow does. How does the following work?
http://stackoverflow.com/tags/foo
http://stackoverflow.com/tags/bar
I've seen a lot of sites that do this, but I still don't know how this is accomplished (I have a LAMP stack).

When a web server gets a request for a URL, it has to decide how to handle it. The classic method was to map the head of the URL to a directory in the file system, then let the rest of the URL navigate to a file in the filesystem. As a result, URLs had file extensions.
But there's no need to do it that way, and most new web frameworks don't. They let the programmer define how to map a URL to code to run, so there's no need for file extensions, because there is no single file providing the response.
In your example, there isn't a "tags" directory containing files "foo" and "bar". The "tags" URL is mapped to code that uses the rest of the URL ("foo" or "bar") as a parameter in a query against the database of tag data.

What you want is clean URLS and you can do it with apache and .htaccess . There may be a better way, but here's how I have been doing it:
http://evolt.org/Making_clean_URLs_with_Apache_and_PHP

That's the beauty and the work of ASP.NET MVC.
No "hiding" - it's just the way ASP.NET MVC handles URL's and maps those "routes" to controller actions on your controller classes.
Quite a big step away from the "classic" ASP.NET Webforms way of doing things.

There are a couple of ways to do it under Apache+PHP, but the essential principle is to make a set of URIs (perhaps all URIs, depending on your site, but you may want different scripts to handle different portions of the site) translate to a single PHP file, which is told what object the user has requested.
The conceptually simplest way is to rewrite every URL to a script, which gets the URI through $_SERVER['REQUEST_URI'] and interprets it as it likes.
The URI rewriting can be done with various methods including mod_rewrite, mod_alias and ErrorDocument (see Apache docs).
Another way is to set up more complex URL rewriting (probably using mod_rewrite) to add the path as a GET variable.
There is also the $_SERVER['PATH_INFO'] variable which is loaded with the non-existent portion of the path. This option requires little or no modification to Apache config files, but reduces the flexibility of your URLs a little.

Modern web development frameworks have support for elegant urls. Check out Django or Ruby on Rails.

If you're using Apache and you simply want to hide the file extensions of static HTML files you can use this .htaccess code:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f # if the requested URL is not a file that exists
RewriteCond %{REQUEST_FILENAME} !-d # and it isn't a directory that exists either
RewriteCond %{REQUEST_FILENAME}\.html -f # but when you put ".html" on the end it is a file that exists
RewriteRule ^(.+)$ $1\.html [QSA] # then serve that file
</IfModule>
Apache mod_rewrite has been called "voodoo, but seriously cool voodoo".
The actual .htaccess code I use on a few sites is like that, but not identical:
<IfModule mod_rewrite.c>
RewriteEngine on
#RewriteRule ^$ index.php [QSA]
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.+)$ $1\.php [QSA]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)$ index.php/$1 [QSA]
</IfModule>
And here is some much longer but far more readable code to do the same thing on a Zeus server. On Zeus, it's called rewrite.script.
# http://drupal.org/node/46508
# get the document root
map path into SCRATCH:DOCROOT from /
# initialize our variables
set SCRATCH:ORIG_URL = %{URL}
set SCRATCH:REQUEST_URI = %{URL}
match URL into $ with ^(.*)\?(.*)$
if matched then
set SCRATCH:REQUEST_URI = $1
set SCRATCH:QUERY_STRING = $2
endif
# prepare to search for file, rewrite if its not found
set SCRATCH:REQUEST_FILENAME = %{SCRATCH:DOCROOT}
set SCRATCH:REQUEST_FILENAME . %{SCRATCH:REQUEST_URI}
# check to see if the file requested is an actual file or
# a directory with possibly an index. don't rewrite if so
look for file at %{SCRATCH:REQUEST_FILENAME}
if not exists then
look for dir at %{SCRATCH:REQUEST_FILENAME}
if not exists then
look for file at %{SCRATCH:REQUEST_FILENAME}.php
if exists then
set URL = %{SCRATCH:REQUEST_URI}.php?%{SCRATCH:QUERY_STRING}
else
set URL = /index.php/%{SCRATCH:REQUEST_URI}?%{SCRATCH:QUERY_STRING}
endif
endif
endif
goto END

Related

Wordpress/Apache rewrite/redirect rule and regex

I need to do some apache rewrite/redirect rules to external webservice in case of 404 error for specific file extensions: .jpg, .png, etc. Wordpress is used here.
So, if 404 occurs at:
https://test.com/folder/subfolder/year/month/filename.jpg
I want to redirect it to:
https://test1.com/folder/subfolder/year/month/filename.jpg (external webservice, not the same phisical server)
I've tried such a configuration in htaccess, didn't work as expected:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*) test1.com/folder/subfolder//$year$\/$month$\/([^\s]+(\.(?i)(png | jpg | gif | svg))$)/
Do you have any ideas how to do it right way?
Any suggestions appreciated.
With your shown samples, attempts; please try following htaccess rules file. These rules are written as per shown domain names which are samples/tests, so you need to change values as per your actual values when you use them in your system. We also need to make sure that both (test.com and test1.com) are sharing same directory structure in your actual apache server.
Also make sure to clear your browser cache before testing your URLs.
RewriteEngine ON
RewriteCond %{HTTP_HOST} ^(?:www\.)?test\.com$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/?$ https://test1.com/$1 [R=301,L]
To "redirect" URLs of the form /folder/subfolder/<year>/<month>/<file>.<png|jpg|gif|svg> where /folder/subfolder/ is static and the other elements are variable and which do not exist on the filesystem you would need to do something like the following before the WordPress code block. ie. before the # BEGIN WordPress section.
# Redirect certain non-existent image files to another server
RewriteRule ^folder/subfolder/\d{4}/\d\d/[\w-]\.(png|jpg|gif|svg)$ https://test1.com/$0 [R=302,L]
# BEGIN WordPress
:
The <year> is a 4-digit number and <month> is a 2-digit number. The filename can consist of the characters 0-9, a-z, A-Z, _ (underscore) and - (hyphen).
This should presumably be a 302 (temporary) redirect, not a 301 (permanent), otherwise if the resource should become available at the source domain then it won't be accessible to those users who have visited the URL before (they will be redirected from cache).
To avoid the external redirect it may be preferable to "proxy" the request to the other domain. (This is invisible to the end user.) Although this potentially involves additional configuration server-side, as you would need to configure the source server as a "reverse proxy". You can then replace the R=302 flag in the above rule with P (proxy).

I cant seem to find how to redirect a trailing url

I cant seem to find how to redirect a trailing url from:
www.domain.com/index.php?option=com_k2&view=itemlist&task=user&id=*
To:
www.domain.com/
Any suggestions?
You can use a RewriteRule in apache configuration. Enable mod_rewrite and .htaccess through httpd.conf. Then, in .htaccess file in root directory place the following
RewriteEngin On
RewriteBase /
RewriteCond %{QUERY_STRING} ^option=com_k2&view=itemlist&task=user&id=.*$
RewriteRule ^index\.php.*$ '' [R,L,QSD]
You have to use RewriteCond to parse the query string, then the RewriteRule uses the flag R to redirect, L to stop processing additional rules, and QSD avoids appending the query string onto the URI. Since you are in web root, you can probably get away without using RewriteBase, but I used it for testing this code because I tested it with .htaccess in a subdirectory. So for someone who wants to do something similar in a subdirectory, you would change the RewriteBase to /sub1/sub2/ to rewrite the url
www.domain.com/sub1/sub2/index.php?option=com_k2&view=itemlist&task=user&id=*
to
www.domain.com/sub1/sub2/
If you do not want the browser to report the change, then use the passthrough flag PT instead of redirect R. There are other helpful flags for case-insensitve matching and more; you can view those in apache docs.

ISAPI Rewrite RewriteRule for domain root username URLs

I am trying to create a root username using ISAPI Rewrite.
E.g. www.mysite.com/myusername
I want this to redirect to...
/user.asp=myusername
Then if the username is not found to load content based on the /folder/
Maybe it would be good to check if a file with folder.asp extension exists and if not redirect to user.asp?username=folder
I know the easy option is to just write the .htaccess to reference:
www.domain.com/user/username
But I really want the root URL?
Thanks in advance,
Chris
I know the easy option is to just write the .htaccess to reference:
I guess your Isapi Rewrite module is Helicon's 3.0.
Checking file/folder existence using Rewrite Module is more efficient than using scripting language.
Write a rule that compatible with your username format (valid characters etc, see the comments).
Check the matched part. Make the redirect if it's not an exists file / folder.
RewriteEngine On
# if the file does not exist
RewriteCond %{DOCUMENT_ROOT}/$1 !-f
# if the folder does not exist
RewriteCond %{DOCUMENT_ROOT}/$1 !-d
# from start to end, "^(\w+)[/]+$" only matches with one or more alphanumeric characters and "_".
# alternatively can end with one or more slashes.
# change [R = 302, L] to [L] if you want make a rewrite instead of redirect.
RewriteRule ^(\w+)[/]*$ /user.asp?username=$1 [R = 302, L]

Rewrite Drupal files directory to sub folder

I am 'merging' two Drupal sites into one multisite installation. But one of the sites has the files saved at <drupal root>/files while the other one saves them at <drupal root>/files/site-2 (which actually is a symlink to <drupal root>/sites/site-2/files). Now I'm looking for a way to 'merge' them without loosing the url structure of my site-1, i.e. I want
http://site-1.com/files to display http://site-1/files/site-1
and keep http://site-2.com/files/site-2 as it was.
I imagine that this can be done through a simple .htaccess mod_rewrite operation, but I don't know much about that. I was trying
RewriteCond %{HTTP_HOST} site-1.com
RewriteRule ^/files(.*)?$ /files/site-1$1 [NC]
but that doesn't seem to work. Could somebody help me?
Classic: The server configuration wasn't correct so that the directives didn't work. Grrr. My solution is now like I said in my first 'answer': Change the paths to use the sub directory and then redirect old files to that folder:
RewriteCond %{HTTP_HOST} site-1.com
RewriteCond %{REQUEST_URI} !^/files/site-1/.*$
RewriteRule ^files/(.*)$ /files/site-1/$1 [L,R=301]
I think internal Drupal paths don't work with rewrites (for example imagecache). That's why I chose this option.
fyi: The replace stuff I used to change the paths in the database is this (in phpmyadmin):
UPDATE files SET filepath = REPLACE(filepath,'files/','files/site-1/');
UPDATE node_revisions SET body = REPLACE(body,'src="/files/','src="/files/site-1/');
UPDATE node_revisions SET teaser = REPLACE(teaser,'src="/files/','src="/files/site-1/');
UPDATE boxes SET body = REPLACE(body,'src="/files/','src="/files/site-1/');

Adding .html onto the end of a URL

I'm currently using Wordpress as a blogging platform but I want to change to use Jekyll to generate the static pages. On Wordpress my URLs use the following format:
/year/month/day/title
but I want to redirect that to
/year/month/day/title.html
and I can't figure out how to do that using mod_rewrite.
Anyone got any ideas?
RewriteEngine On
# Only if the URI is not a normal file
RewriteCond %{REQUEST_FILENAME} !-s
# ... or a symbolic link
RewriteCond %{REQUEST_FILENAME} !-l
# ... rewrite everything that ends on .html to the stripped down URL
RewriteRule (.+)\.html$ $1 [L]
# Alternatively, if you want to be more specific about the scheme, you can use this
# RewriteRule ^/([0-9]{4})/([0-9]{2})/([0-9]{2})/([^/]+)\.html$ $1/$2/$3/$4 [L}
The above should give you some pointers on how to properly rewrite the URL to the scheme you desire. This example transparently rewrites everything that ends on .html (except actual files) to the same URL without the .html appended to it.
I believe you can just go to Admin → Settings → Permalinks and set the permalinks to custom with a value of:
/%year%/%monthnum%/%day%/%postname%.html

Resources