Server side includes as a templating/layout technique - .htaccess

I'm making a website for a company, and I wanted to use something like ASP.NET MVC layout pages to dynamically load the content into the layout, but the hosting provider used by the company doesn't support ASP.NET. I assumed they supported Node.js, because they said the only thing they didn't support was .NET, so I used a templating library called Embedded JavaScript Templates (http://ejs.co/) with Express.js, but then found out the hosting provider doesn't support Node, either.
Server side includes are definitely supported, but my question is can I use them to take the filename from the url where the user navigated, pass that into the server side include in the index.html page (the page I'm trying to use as the layout page) and have the web server inject the content where the include tag is? So far all the examples I've seen for server side includes show the file name entered as a literal, such as:
<!--#include virtual="physicians.html" -->
Whereas I want the file included to be determined by what the user entered when they navigated to the site. If it was http://website.com/physicians.html, then the index.html file should be loaded with "physicians.html" injected where the include was. Something like this (which obviously doesn't work):
<!--#include virtual="${REQUEST_URI}" -->
I also tried adding the following to the .htaccess file (note I am aware it doesn't enable server-side includes. I did enable SSI later and SSI was working, though not in the way I wanted it to as mentioned before):
<ifModule mod_rewrite.c>
Options +FollowSymLinks
IndexIgnore */*
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.html
</ifModule>
This came from http://krasimirtsonev.com/blog/article/deep-dive-into-client-side-routing-navigo-pushstate-hash. I used the above .htaccess configuration with his client-side library Navigo and some AJAX. Here's the JavaScript for loading content into the index.html file (/views is where the partial views are stored):
function loadViewContent(viewPath)
{
$('#main-content').load(viewPath, navSetActive);
}
var root = "http://www.caduceuscorporation.com";
var router = new Navigo(root);
router.on({
'/': loadViewContent.bind(this, "views/home.html"),
'index.html': loadViewContent.bind(this, "views/home.html"),
'/:page': function(params) {
loadViewContent("views/" + params.page + ".html");
}
})
.resolve();
It works great, except if I enter an invalid filename then it goes into an endless loop of loading index.html within itself. What the .htaccess configuration is doing is if the path is invalid, the server sends back the content for index.html, hence the infinite loop of index.html loading itself within itself.
Is there a way to use server-side includes to load content based on the URL the user entered, rather than a predetermined file? Or is there a different .htaccess configuration I need to use? I hope I have made it clear what I am trying to do. If SSI or a different .htaccess configuration doesn't work, I guess I'll have to use PHP maybe. I know the hosting provider supports that for certain.

I found a solution that works almost exactly like ASP.NET MVC layout pages, which is basically what I was asking for in my original question, but uses server-side includes (SSI) instead. I first had to figure out the right syntax for entering the variable name into the virtual parameter of the include tag. In my case, it should look like this:
<!--#include virtual="views${REQUEST_URI}.html" -->
And it should be entered into the "layout page" (in my case, index.html) where you want the "partial view" page to appear. So if I enter an address like https://example.com/physician, the server will translate "physician" to "views/physician.html" as the local relative path (since the views directory in my local web root is where my views are stored) and the content of that file will be inserted into index.html where the include tag is.
There's one more step. I modified my .htaccess file to look like this:
<ifModule mod_rewrite.c>
RewriteEngine on
Options +Includes
AddHandler server-parsed .html
IndexIgnore */*
RewriteCond %{DOCUMENT_ROOT}/views%{REQUEST_URI}.html -f
RewriteRule .* index.html
RewriteRule ^/$ index.html
</ifModule>
RewriteCond with the -f flag tells the server that if there is a file in the path listed after RewriteCond, then apply the RewriteRule following the RewriteCond. The DOCUMENT_ROOT after RewriteCond is necessary, because when using -f, relative paths don't work.
RewriteRules return a page based on the path the user entered into her browser. They take a regular expression matching the path the user entered. The first RewriteRule has the regular expression .*, which matches any path the user entered. But the RewriteCond before it tells the RewriteRule to only be applied when the file in the path the user entered exists in the views folder on the server. If not, the first RewriteRule is not applied. Otherwise, the server will send back index.html with the include tag replaced by the page the user entered, as described above. The final RewriteRule only matches /, otherwise there would be no way to go to the website root.
I actually put some conditional tags into my index.html file surrounding the include tag:
<!--#if expr="${REQUEST_URI} != '/'" -->
<!--#include virtual="views${REQUEST_URI}.html" -->
<!--#else -->
<!--#include virtual="views/home.html" -->
<!--#endif -->
This way, the home page can be loaded when the user goes to the website root, or otherwise the user couldn't access the home page without entering /home.
Resources I used:
https://httpd.apache.org/docs/trunk/howto/ssi.html (Apache SSI Tutorial)
RewriteRule htaccess if a file exists (Stack Overflow post)

Related

htaccess for local testing and live server

I'm close, to my final solution I think.
The .htaccess looks like this:
Options +FollowSymLinks
RewriteEngine On
RewriteBase /myproject/development/
RewriteRule ^((?!index\.php)[^/]+)/?$ index.php?page=$1 [L]
RewriteRule ^((?!index\.php)[^/]+)/([A-Za-z0-9]+)/([0-9]+)/([0-9]+)/?$ index.php?page=$1&keyword=$2&zip=$3&range=$4 [L,R]
I don't need the RewriteBase for the 1st rule(was a little surprised about that) but I need it if I add the 2nd rule and open this URL:
//localhost/myproject/development/somepage/test/13245/50
Otherwise the page will be opened but of course without the stylesheets and javaScripts can be found then.
1.) Target: I want to use the 2nd rewriteRule without changing or adding a rewriteBase. What do I need to change in the .htaccess so I can keep testing my project without a rewriteBase.
Why: As I asked before I want to test my project locally and on the live-server without changing too much on the project configuration.
2.) The [R] Flag If I request
//localhost/myproject/development/somepage/test/53229/2000
Of course in the adressline then we have this URL
//localhost/myproject/development/index.php?page=somepage&keyword=test&zip=12345&range=2000
To avoid this behaviour I simply should remove the R-Flag. But then the CSS and JS can't be found anymore. Also Here I'm looking for a solution without rewritebase, basepath, virtual host, etc. if possible.
Here is where I started:
Rewrite rules for localhost AND live envoirement
By the looks, you don't want the R flag on the 2nd RewriteRule. That defeats the object of your "pretty" URLs.
But then the CSS and JS can't be found anymore.
Because you are using relative paths to your CSS and JS files. Either change your paths to root-relative (starting with a slash), or use the base element in the head section of your pages, to indicate the URL that all relative URLs are relative to:
<base href="http://www.example.com/page.html">
More Information:
https://developer.mozilla.org/en/docs/Web/HTML/Element/base
I don't need the RewriteBase for the 1st rule(was a little surprised about that)
You don't need the RewriteBase for the 1st rule (an internal rewrite) because the directory-prefix (the filesystem path that lead to this .htaccess file) is automatically added back on relative path substitutions.
However, for external redirects (ie. R flag), the directory-prefix does not make sense, so you either need to specify a root-relative (starting with a slash) or absolute URL. Or specify the appropriate RewriteBase directive, which overrides what URL-path will be added for relative substitutions (that's all it does).

Clean URL rewriting rule

right now my url looks like this:
http://domain.com/en/c/product%2C-product2%2C-product3/82
where last number is category numer.
And im trying to rewrite it and redirect user to url which should look this one:
http://domain.com/82/product-product2-product3
The clue is I want to hide "en/c/" part and clean url from commas and blank spaces. I'm completely green in rewriting.
Any ideas?
You can use these 2 rules in your root .htaccess for that:
RewriteEngine On
RewriteBase /
RewriteRule ^en/c/([^,\s]*)[,\s]+([^,\s]*)/(\d+)/?$ $3/$1$2 [NC,L,NE,R=302]
RewriteRule ^(en/c)/([^,\s]*)[,\s]+(.*)/(\d+)/?$ $1/$2$3/$4 [NC,L]
In order for this to work, we need to tell the server to internally redirect all requests for the URL "url1" to "url2.php". We want this to happen internally, because we don't want the URL in the browser's address bar to change.
To accomplish this, we need to first create a text document called ".htaccess" to contain our rules. It must be named exactly that (not ".htaccess.txt" or "rules.htaccess"). This would be placed in the root directory of the server (the same folder as "url2.php" in our example). There may already be an .htaccess file there, in which case we should edit that rather than overwrite it.
The .htaccess file is a configuration file for the server. If there are errors in the file, the server will display an error message (usually with an error code of "500").
If you are transferring the file to the server using FTP, you must make sure it is transferred using the ASCII mode, rather than BINARY. We use this file to perform 2 simple tasks in this instance - first, to tell Apache to turn on the rewrite engine, and second, to tell apache what rewriting rule we want it to use. We need to add the following to the file:
RewriteEngine On # Turn on the rewriting engine
RewriteRule ^url1/?$ url2.php [NC,L] # Handle requests for "url1"

Pretty URL via separate folder and index.html file inside or rule in .htaccess

I have static site (html + css) generated by nanoc.
It works under Apache.
I want use pretty url instead of .html suffix at the end. Like this:
http://domain.ru
http://domain.ru/page/page1/
http://domain.ru/page/page2/
instead of
http://domain.ru/index.html
http://domain.ru/page/page1.html
http://domain.ru/page/page2.html
So, the 1st way is to create the separate folders with names page1 and page2 and place inside index.html files with corresponding content. When client does request:
http://domain.ru/page/page1/ is loaded file page1/index.html
The 2nd way is to have such files structure:
page (folder)
- page1.html (file)
- page2.html (file)
and create rule for .htaccess file in root of the site:
RewriteEngine on
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteRule ^(.+)/$ /$1.html
So, the question is which way is better ? May be there are some additional costs of using
rewrite rules or pitfalls? May be there are some good practices for this questions for static generated sites.
PS:
In any way i use .htaccess file: i need switch on utf-8 encoding, enable 404 error handling , disallow browse folders
Thanks and sorry for bad english :)
I prefer to use index.html in directories, because it is server -independent. I don’t think there’s a good reason not to do it that way.

Hide admin folder from url

Current URL
http://www.example.com/admin/data/img/gallery/myimages.jpg
http://www.example.com/admin/data/content/mycontents.html
So
Current SCRIPTS / HTMLS / FILES OF WEBPAGE CONTAIN and shows in browser source code
<img src="/admin/data/img/gallery/myimage.jpg">
<?php include("/admin/data/content/mycontents.html"); ?>
This is "CMS system" in a folder named "admin"
What i want to do is Hide the admin folder from every script /php/html output to browser.
So no body can see or search engines can't capture this area (Security concern)
So when the browser output the content or script it will rewrite the above urls to this
Removing the admin
http://www.example.com/data/img/gallery/myimages.jpg
http://www.example.com/data/content/mycontents.html
Inside browser source code
<img src="/data/img/gallery/myimage.jpg">
or
removing the data too
http://www.example.com/img/gallery/myimages.jpg
http://www.example.com/content/mycontents.html
Kindly help also it must work for www.example.com as well as example.com
Solution through htaccess and mod_rewrite
i do not have access to httpd.conf
Also i do not want to move the folder a lots of scripts are there in the folder so have to write a lot.
Also tell me where should i place it in the root or in the admin folder
Thank you
You could try adding this to the .htaccess file in your document root (where the "admin" folder is in):
RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}/admin/data/%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}/admin/data/%{REQUEST_URI} -d
RewriteRule ^(.*)$ /admin/data/$1 [L]
The conditions check that if the request URI gets prepended with "/admin/data/", if it points to an existing file or directory. If it does, then rewrite the URI so that there's an "/admin/data/" in front of the request. If you don't want to be able to map directories into /admin/data, then remove the second condition (the one with -d) and remove the [OR] flag from the first.

.htaccess rewriting - URLs with multi level directories

I have a page deals.php which is placed at root directory that is being accessed by number of internal URLs with multi directory levels. for example this page would be accessed by both following urls.
http://domain/flights/asia/bangkok
http://domain/flights/bangkok
I am using this code in .htaccess to redirect to deals.php
Options +FollowSymlinks
RewriteEngine on
RewriteRule ^flights/asia/([^/]+)/?$ deals.php?country=$1 [NC]
RewriteRule ^flights/([^/]+)/?$ deals.php?country=$1 [NC]
Now the problem here coming is that on deals.php all the images, script and style sheet files are not opening properly. If I try to fix it against one URL by placing ../../ in addresses of all images, script and css, it dont work for other URL.
How to solve this problem? what are the options?
Easy: DO NOT use ../ in links to any resources (images/css/js/etc) -- always use URL that is relative to the WEBSITE ROOT -- that is a "requirement" when you dealing with nice/not-real/rewritten URLs as such URL rarely points to the physical file location.
Lets assume you have a logo that is located at http://www.example.com/images/logo.png.
Now, instead of ../images/logo.png and/or ../../images/logo.png ALWAYS use /images/logo.png.
i think what you want is placing an baseurl in html page, so all the relative path will related to the baseurl, not the current URL in the navigator bar

Resources