URL 重写 eXist-db 中的嵌套目录
URL rewriting for nested directories in eXist-db
我想将安全页面分离到一个目录中。
最简单的场景:
home/
|-index.html
|-controller.xql
|-secure/
|-authentication-test.html
+-security.html
目前,除了逃离 secure
directory/path 之外,一切正常。问题是当我登录时,index.html
页面上的每个 link 都以 url 的 /secure/
部分为前缀。这意味着在注销后,我不会被发送到 index.html
,而是发送到 /secure/index.html
,它不存在。它让我想起了 context 之类的东西。我不知何故 锁定 在嵌套目录中,“上下文已更改”。我还没有更改 controller-config.xml
。
我的控制器:
xquery version "3.0";
import module namespace login="http://exist-db.org/xquery/login" at "resource:org/exist/xquery/modules/persistentlogin/login.xql";
declare variable $exist:path external;
declare variable $exist:resource external;
declare variable $exist:controller external;
declare variable $exist:prefix external;
declare variable $exist:root external;
declare variable $local:login_domain := "karolinum-x";
declare variable $local:user := $local:login_domain || '.user';
let $logout := request:get-parameter("logout", ())
let $set-user := login:set-user($local:login_domain, (), false())
return
if ($exist:path eq '') then
<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
<redirect url="{request:get-uri()}/"/>
</dispatch>
else if ($exist:path eq "/") then
<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
<redirect url="index.html"/>
</dispatch>
else if ($exist:path eq "/secure/authentication-test.html") then
if (request:get-attribute("karolinum-x.user")) then
<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
<view>
<forward url="{$exist:controller}/modules/view.xql">
<set-attribute name="isUser" value="true"/>
<set-attribute name="$exist:prefix" value="{$exist:prefix}"/>
<set-attribute name="$exist:controller" value="{$exist:controller}"/>
</forward>
</view>
<error-handler>
<forward url="{$exist:controller}/error-page.html" method="get"/>
<forward url="{$exist:controller}/modules/view.xql"/>
</error-handler>
</dispatch>
else
<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
<forward url="{$exist:controller}/security.html"/>
<view>
<forward url="{$exist:controller}/modules/view.xql">
<set-attribute name="$exist:prefix" value="{$exist:prefix}"/>
<set-attribute name="$exist:controller" value="{$exist:controller}"/>
<set-header name="Cache-Control" value="no-cache"/>
</forward>
</view>
<error-handler>
<forward url="{$exist:controller}/error-page.html" method="get"/>
<forward url="{$exist:controller}/modules/view.xql"/>
</error-handler>
</dispatch>
else if (ends-with($exist:resource, ".html")) then
<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
<view>
<forward url="{$exist:controller}/modules/view.xql"/>
</view>
<error-handler>
<forward url="{$exist:controller}/error-page.html" method="get"/>
<forward url="{$exist:controller}/modules/view.xql"/>
</error-handler>
</dispatch>
(: Resource paths starting with $shared are loaded from the shared-resources app :)
else if (contains($exist:path, "/$shared/")) then
<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
<forward url="/shared-resources/{substring-after($exist:path, '/$shared/')}">
<set-header name="Cache-Control" value="max-age=3600, must-revalidate"/>
</forward>
</dispatch>
else
(: everything else is passed through :)
<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
<cache-control cache="yes"/>
</dispatch>
您面临的问题归结为:您的主模板 templates/page.html
包含具有相对 link 的菜单项,因此当您进入子目录时,link 休息。这将发生在您使用需要在 URL 层次结构的各个级别显示的相对 link 的任何其他页面中。这是您的 templates/page.html
的摘录,显示了相对 links:
<ul class="nav navbar-nav">
<li class="dropdown" id="about">
<a href="index.html" class="dropdown-toggle">Home</a>
</li>
<li class="dropdown" id="test">
<a href="test/url.html" class="dropdown-toggle">Test</a>
</li>
</ul>
这里,index.html
和test/url.html
都是相对的。因此,如果您从 index.html
开始单击菜单 link 到 test/url.html
,新菜单项是相对于 test
目录的,因此单击任一菜单项都会带您到 test/index.html
或 test/test/url.html
- 依此类推。要克服这个问题,您至少有三个选择:
(1) 使用硬编码的绝对 link,例如 /exist/apps/my-app/index.html
和 /exist/apps/my-app/test/url.html
。这是最简单的。
(2) 使用类似于 controller.xql 处理 $shared
-前缀 URL 的方法。例如,您可以使 links $app/index.html
,然后向 controller.xql 添加一个条件来处理 $app
-prefixed URLs,例如 $app/index.html
或 $app/test/url.html
。这会导致多个 URL 解析到同一个资源,所以我不是特别喜欢这种方法,但它确实有效。
或 (3) 像 hsg-shell 应用程序那样使用模板调用函数 app:fix-links
。参见 https://github.com/eXistSolutions/hsg-shell/blob/master/modules/app.xqm#L62 and https://github.com/eXistSolutions/hsg-shell/blob/master/templates/site.html#L45。虽然这意味着您要在应用程序中以这种方式处理的所有 link 都使用 $app
作为前缀,但它确实为深度嵌套的 URL 以及应用程序结构和名称的未来更改提供了极大的灵活性等
我想将安全页面分离到一个目录中。
最简单的场景:
home/
|-index.html
|-controller.xql
|-secure/
|-authentication-test.html
+-security.html
目前,除了逃离 secure
directory/path 之外,一切正常。问题是当我登录时,index.html
页面上的每个 link 都以 url 的 /secure/
部分为前缀。这意味着在注销后,我不会被发送到 index.html
,而是发送到 /secure/index.html
,它不存在。它让我想起了 context 之类的东西。我不知何故 锁定 在嵌套目录中,“上下文已更改”。我还没有更改 controller-config.xml
。
我的控制器:
xquery version "3.0";
import module namespace login="http://exist-db.org/xquery/login" at "resource:org/exist/xquery/modules/persistentlogin/login.xql";
declare variable $exist:path external;
declare variable $exist:resource external;
declare variable $exist:controller external;
declare variable $exist:prefix external;
declare variable $exist:root external;
declare variable $local:login_domain := "karolinum-x";
declare variable $local:user := $local:login_domain || '.user';
let $logout := request:get-parameter("logout", ())
let $set-user := login:set-user($local:login_domain, (), false())
return
if ($exist:path eq '') then
<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
<redirect url="{request:get-uri()}/"/>
</dispatch>
else if ($exist:path eq "/") then
<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
<redirect url="index.html"/>
</dispatch>
else if ($exist:path eq "/secure/authentication-test.html") then
if (request:get-attribute("karolinum-x.user")) then
<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
<view>
<forward url="{$exist:controller}/modules/view.xql">
<set-attribute name="isUser" value="true"/>
<set-attribute name="$exist:prefix" value="{$exist:prefix}"/>
<set-attribute name="$exist:controller" value="{$exist:controller}"/>
</forward>
</view>
<error-handler>
<forward url="{$exist:controller}/error-page.html" method="get"/>
<forward url="{$exist:controller}/modules/view.xql"/>
</error-handler>
</dispatch>
else
<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
<forward url="{$exist:controller}/security.html"/>
<view>
<forward url="{$exist:controller}/modules/view.xql">
<set-attribute name="$exist:prefix" value="{$exist:prefix}"/>
<set-attribute name="$exist:controller" value="{$exist:controller}"/>
<set-header name="Cache-Control" value="no-cache"/>
</forward>
</view>
<error-handler>
<forward url="{$exist:controller}/error-page.html" method="get"/>
<forward url="{$exist:controller}/modules/view.xql"/>
</error-handler>
</dispatch>
else if (ends-with($exist:resource, ".html")) then
<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
<view>
<forward url="{$exist:controller}/modules/view.xql"/>
</view>
<error-handler>
<forward url="{$exist:controller}/error-page.html" method="get"/>
<forward url="{$exist:controller}/modules/view.xql"/>
</error-handler>
</dispatch>
(: Resource paths starting with $shared are loaded from the shared-resources app :)
else if (contains($exist:path, "/$shared/")) then
<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
<forward url="/shared-resources/{substring-after($exist:path, '/$shared/')}">
<set-header name="Cache-Control" value="max-age=3600, must-revalidate"/>
</forward>
</dispatch>
else
(: everything else is passed through :)
<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
<cache-control cache="yes"/>
</dispatch>
您面临的问题归结为:您的主模板 templates/page.html
包含具有相对 link 的菜单项,因此当您进入子目录时,link 休息。这将发生在您使用需要在 URL 层次结构的各个级别显示的相对 link 的任何其他页面中。这是您的 templates/page.html
的摘录,显示了相对 links:
<ul class="nav navbar-nav">
<li class="dropdown" id="about">
<a href="index.html" class="dropdown-toggle">Home</a>
</li>
<li class="dropdown" id="test">
<a href="test/url.html" class="dropdown-toggle">Test</a>
</li>
</ul>
这里,index.html
和test/url.html
都是相对的。因此,如果您从 index.html
开始单击菜单 link 到 test/url.html
,新菜单项是相对于 test
目录的,因此单击任一菜单项都会带您到 test/index.html
或 test/test/url.html
- 依此类推。要克服这个问题,您至少有三个选择:
(1) 使用硬编码的绝对 link,例如 /exist/apps/my-app/index.html
和 /exist/apps/my-app/test/url.html
。这是最简单的。
(2) 使用类似于 controller.xql 处理 $shared
-前缀 URL 的方法。例如,您可以使 links $app/index.html
,然后向 controller.xql 添加一个条件来处理 $app
-prefixed URLs,例如 $app/index.html
或 $app/test/url.html
。这会导致多个 URL 解析到同一个资源,所以我不是特别喜欢这种方法,但它确实有效。
或 (3) 像 hsg-shell 应用程序那样使用模板调用函数 app:fix-links
。参见 https://github.com/eXistSolutions/hsg-shell/blob/master/modules/app.xqm#L62 and https://github.com/eXistSolutions/hsg-shell/blob/master/templates/site.html#L45。虽然这意味着您要在应用程序中以这种方式处理的所有 link 都使用 $app
作为前缀,但它确实为深度嵌套的 URL 以及应用程序结构和名称的未来更改提供了极大的灵活性等