服务器端包括作为模板/布局技术

时间:2018-07-03 08:24:06

标签: .htaccess server-side-includes

我正在为一家公司创建网站,我想使用ASP.NET MVC布局页面之类的内容将内容动态加载到布局中,但是该公司使用的托管提供商不支持ASP.NET。 。我以为他们支持Node.js,因为他们说他们唯一不支持的是.NET,所以我在Express.js中使用了名为Embedded JavaScript Templates(http://ejs.co/)的模板库,但后来发现托管服务提供商也不支持Node。

绝对支持服务器端包含,但是我的问题是我可以使用它们从用户导航的URL中获取文件名,并将其传递到index.html页面(我正在尝试的页面)中的服务器端用作布局页面),并让网络服务器将内容注入到包含标签所在的位置?到目前为止,我在服务器端看到的所有示例都包括显示以文字形式输入的文件名,例如:

<!--#include virtual="physicians.html" -->

我希望包含的文件由用户导航到该站点时输入的内容确定。如果它是http://website.com/physicians.html,则应该在包含位置的位置插入index.html文件,并在其中插入“ physicians.html”。像这样的东西(显然不起作用):

<!--#include virtual="${REQUEST_URI}" -->

我还尝试将以下内容添加到.htaccess文件中(请注意,我知道它不会启用服务器端包含。我确实启用了SSI,SSI仍在工作,尽管不是我所希望的那样之前):

<ifModule mod_rewrite.c>
  Options +FollowSymLinks
  IndexIgnore */*
  RewriteEngine On
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule (.*) index.html
</ifModule>

这来自http://krasimirtsonev.com/blog/article/deep-dive-into-client-side-routing-navigo-pushstate-hash。我将上述.htaccess配置与他的客户端库Navigo和一些AJAX一起使用。这是将内容加载到index.html文件中的JavaScript(/ views是部分视图的存储位置):

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();

它工作得很好,除非我输入了无效的文件名,否则它将陷入无休止的循环,在其内部加载index.html。 .htaccess配置正在做的是,如果路径无效,服务器将发回index.html的内容,因此index.html无限循环将自身加载到内部。

是否有一种使用服务器端包含的方法来基于用户输入的URL而不是预定文件加载内容?还是我需要使用其他的.htaccess配置?我希望我已经明确了我要做什么。如果SSI或其他.htaccess配置不起作用,我想我可能不得不使用PHP。我知道托管服务提供商一定会支持。

1 个答案:

答案 0 :(得分:0)

我找到了一个几乎与ASP.NET MVC布局页面完全一样的解决方案,这基本上是我最初提出的问题,但是使用服务器端包含(SSI)。我首先必须弄清楚将变量名输入到include标记的虚拟参数中的正确语法。就我而言,它应该像这样:

<!--#include virtual="views${REQUEST_URI}.html" -->

它应该输入到“布局页面”(在我的情况下为index.html)中,您希望在其中显示“部分视图”页面。因此,如果我输入诸如https://example.com/physician之类的地址,则服务器会将“医生”转换为“本地相对路径”(因为存储我的本地根目录中的views目录)是本地相对路径。并且该文件的内容将插入到include。标签所在的index.html中。

还有一步。我修改了.htaccess文件,使其看起来像这样:

<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>

带有-f标志的RewriteCond告诉服务器,如果在RewriteCond之后列出的路径中有文件,则在RewriteCond之后应用RewriteRule。 RewriteCond之后的DOCUMENT_ROOT是必需的,因为使用-f时,相对路径不起作用。

RewriteRules根据用户在浏览器中输入的路径返回页面。它们采用与用户输入的路径匹配的正则表达式。第一个RewriteRule具有正则表达式。*,它与用户输入的任何路径匹配。但是,RewriteCond告诉RewriteRule仅在用户输入的路径中的文件存在于服务器的views文件夹中时才应用。如果不是,则不应用第一个RewriteRule。否则,服务器将发回index.html,其中包含标记被用户输入的页面替换,如上所述。最终的RewriteRule仅匹配/,否则将无法访问网站根目录。

我实际上将一些条件标签放入了包含标签周围的index.html文件中:

<!--#if expr="${REQUEST_URI} != '/'" -->
<!--#include virtual="views${REQUEST_URI}.html" -->
<!--#else -->
<!--#include virtual="views/home.html" -->
<!--#endif -->

这样,可以在用户转到网站根目录时加载主页,否则,如果不输入/ home,用户将无法访问主页。

我使用的资源:

https://httpd.apache.org/docs/trunk/howto/ssi.html(Apache SSI教程)

RewriteRule htaccess if a file exists(堆栈溢出帖子)