动态页面的 eXist-db URL 映射

eXist-db URL mapping for a dynamic page

我的 eXist-db 应用程序中有许多动态页面,直到现在都通过硬编码输入进行了测试。现在,我不得不冒险进入一个我最不适应的领域:URL mapping/rewriting in eXist-db.

这是基本情况。当用户想在我的站点上查看中世纪文档时,他们可以搜索列表并单击 link 或直接输入 URL。无论如何,url 将是:

www.foo.com/doc/MS609-0020

其中 /doc/ 表示您正在查看文档,而 MS609-0020 实际上是文档的名称(反映了 XML 文件即 MS609-0020.xml)。

所有此类文档都将通过位于以下位置的通用页面输出:

/db/apps/deheresi/document.html

document.html 包含的模板需要请求中的文档名称 MS609-0020.xml 才能知道要处理的内容。我已将此全局可用变量命名为 $currentdoc。使用此变量,不同的模板获取 assemble document.html.

所需的数据

然后HTML发送到www.foo.com/doc/MS609-0020

下的浏览器

如果未找到文档名称,用户将被定向到 'document not found page'。

如您所见,我的解释是基本的 - 反映了我仍然使用 eXist 和 XQuery 进行训练的事实。

我已经通读了 Siegel/Retter 的 eXist 书中的章节,但是如何在模块中完成重新映射,并通过所需的 parameters...我不明白不管我如何破解这个。

我将非常感谢任何指导,从伪代码和说明到一些片段。一旦我看到如何处理这个请求,那么它就会作为一种练习为我整理出来。

非常感谢。

注意:我应该补充一点,这将是一个 public 站点,不需要查看文档的权限。

注意 2:一旦符合条件,我将悬赏此问题。

下面是 Siegel/Retter 书中的图表。

此答案仅涵盖基本 URL 重写,假设 eXist 应用程序是使用我称之为 "basic" eXist 应用程序架构构建的:

  • 我们称之为 "my-app" 的应用程序存储在 /db/apps/my-app
  • 未对 EXIST_HOME/tools/jetty/etc 中的 Jetty 配置文件、EXIST_HOME/webapp/WEB-INF/web.xml 中的 XQuery servlet 配置文件或 [=16] 中重写的 eXist URL 的基本配置进行任何修改=].
  • 这意味着可以在 http://localhost:8080/exist/apps/my-app 访问该应用程序。 (如果目标是通过像 http://my-server/ 这样的 URL 为这个应用程序提供服务,并将其路由到位于 http://localhost:8080/exist/apps/my-app 的 eXist,这最好由反向代理服务器处理,这超出了范围"basic" eXist 应用架构。)
  • 我们将通过 eXist 的 URL 重写工具处理 URL 重写 - 即,写入 controller.xql 文件 - 而不是通过 RESTXQ。

根据这些假设,我们可以创建完全自定义的 URLs,允许我们采用 URL,例如:

  • http://localhost:8080/exist/apps/my-app/doc.xq?filename=my-document.xml

并通过以下方式提供相同的资源:

  • http://localhost:8080/exist/apps/my-app/doc/my-document

为此,我们需要在根目录中创建一个新的 XQuery 主模块,命名为 controller.xql(必须准确地称呼它,我们称它为应用程序的 "controller")您的应用程序集合:/db/apps/my-app/controller.xql。这是一个特殊的模块,当请求到达 /apps URL space(例如 http://localhost:8080/exist/apps/...)中的路径时,eXist 首先查找它。虽然通常一个应用程序只有一个控制器,但 eXist 支持多个控制器; eXist 在目标集合中查找,然后向上查找集合树,从最深的分支到根 /db/apps 集合。

控制器的目的是获取有关请求的信息 - 请求的路径和有关应用程序上下文的其他信息 - 和 return 一种特殊的指令,它告诉 eXist 如何路由请求。有关请求的关键信息在一系列 外部变量 中暴露给您的查询(您不必为您定义 eXist 集并且您可以引用的变量),包括,最重要的是,$exist:path - 包含控制器的集合路径之后的请求部分 URL。所以在上面的 URL 中,$exist:path 等于 /doc/my-document.

现在,让我们创建采用此路径并转发此请求的指令(使用 filename 参数制定到您的实际端点:

xquery version "3.1";

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;

if (starts-with($exist:path, "/doc/")) then
    <dispatch xmlns="http://exist.sourceforge.net/NS/exist">
        <forward url="{$exist:controller}/doc.xq">
            <add-parameter name="filename" value="{$exist:resource}.xml"/>
        </forward>
    </dispatch>

else
    <ignore xmlns="http://exist.sourceforge.net/NS/exist"/>

在第一个代码块(序言)中,此控制器显式声明了 eXist 提供给控制器的变量。在查询的主要部分,条件表达式处理两种情况:

  1. 如果请求的路径以 /doc/ 开头,那么我们希望请求由 doc.xq 处理 - 我们应用程序中位于 /db/apps/my-app/doc.xq 的 XQuery 模块。我们可以将 /db/apps/my-app 替换为 $exist:controller 而不是键入此完整路径 - 这是找到活动控制器的集合的数据库路径。我们也知道 doc.xq 需要一个 filename 参数,所以我们明确地从 $exist:resource 变量构造它,它总是在最终的 URL 之后为我们提供所请求的部分斜杠 - 例如,my-document 在我们上面的示例 URL 中。从控制器将请求转发到的查询(例如doc.xq)的角度来看,它认为它直接收到了请求,并且可以通过request:get-parameter()函数访问请求参数。例如,doc.xq 可以简单地包含:

    xquery version "3.1";
    
    let $doc := request:get-parameter("filename", ())
    return
        <p>Who's looking for {$filename}?</p>
    

    上面 URL 的请求将 return <p>Who's looking for my-document.xml?</p>.

  2. 对于任何其他请求,我们将允许这些请求通过而不执行任何转发或其他 URL 操作。

如果您正在使用 eXist 的 HTML 模板工具,您可能会将请求转发到模板 (document.html) 而不是查询 (doc.xq)。在这种情况下,指令变得 little 更复杂:

    <dispatch xmlns="http://exist.sourceforge.net/NS/exist">
        <forward url="{$exist:controller}/document.html"/>
        <view>
            <forward url="{$exist:controller}/modules/view.xql">
                <add-parameter name="filename" value="{$exist:resource}.xml"/>
            </forward>
        </view>
    </dispatch>

在这里,我们将请求转发给 document.html,但随后结果会通过 eXist 的模板处理程序模块传递,该模块通常存储在应用程序的 modules/view.xql 文件中。 (请注意,<add-parameter> 指令已移至第二个 <forward> 指令。)

其他外部变量(即 $exist:root$exist:prefix)和其他类型的指令(即 <redirect> 和其他子元素)在 eXist 文档页面中进行了描述关于 URL 重写,http://exist-db.org/exist/apps/doc/urlrewrite。虽然该页面当前警告它已过时,但我认为它仍然是一个很好的资源。

eXist URL 重写功能的优势在于您可以使用 XQuery 的完整表现力来确定您的应用程序如何路由和接收 URL。缺点是控制器会变成一长串难以维护的条件;只是尽量保持控制器逻辑尽可能简单。学习外部变量也可能需要一些时间;我建议充分利用日志记录(通过 util:logconsole:log 函数输出外部变量的值和有关请求的其他信息,可通过 request:get-url() 和其他request:get-* 函数)以查看每个请求的情况,直到您掌握它。您可能还会发现调查其他可获得源代码的应用程序中的控制器文件很有帮助,并在此处提出更多问题!