В этом ответе, который охватывает только базовую перезапись URL-адреса, предполагается, что приложение eXist построено с использованием так называемой «базовой» архитектуры приложения eXist:
- Приложение, которое мы назовем«my-app» хранится в
/db/apps/my-app
. - Не было внесено никаких изменений в файлы конфигурации Jetty в
EXIST_HOME/tools/jetty/etc
, файл конфигурации сервлета XQuery в EXIST_HOME/webapp/WEB-INF/web.xml
или базовую конфигурацию для eXist.Перезапись URL-адреса на webapp/WEB-INF/controller-config.xml
. - Это означает, что к приложению можно получить доступ на
http://localhost:8080/exist/apps/my-app
.(Если цель состоит в том, чтобы обслуживать это приложение через URL-адрес, такой как http://my-server/
, и направить его в eXist на http://localhost:8080/exist/apps/my-app
, это лучше всего обрабатывать обратным прокси-сервером, который выходит за рамки «базовой» архитектуры приложения eXist.) - Мы будем обрабатывать перезапись URL-адреса с помощью средства перезаписи URL-адреса eXist, т. Е. Записывать файл
controller.xql
, а не через RESTXQ.
С этими допущениями мы можем создавать полностью настраиваемые URL-адреса, что позволяет нам брать 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
(он должен бытьэто называется именно так, и мы назовем его «контроллером» приложения в корневой коллекции вашего приложения: /db/apps/my-app/controller.xql
.Это специальный модуль, который eXist ищет первым, когда приходит запрос на путь в адресном пространстве /apps
(например, http://localhost:8080/exist/apps/...
).Хотя обычно приложение имеет только один контроллер, eXist поддерживает несколько контроллеров;eXist ищет в целевой коллекции, а затем вверх по дереву коллекции, от самой глубокой ветви до корневой /db/apps
коллекции.
Цель контроллера - получить информацию о запросе - запрошенный путь и другую информациюо контексте приложения - и возвращает специальный вид директивы, которая сообщает 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 предоставляет контроллеру. В основной части запроса условное выражение обрабатывает два случая:
Если запрошенный путь начинается с /doc/
, то мы хотим, чтобы запрос обрабатывался doc.xq
- модулем XQuery в нашем приложении по адресу /db/apps/my-app/doc.xq
. Вместо того, чтобы вводить этот полный путь,мы можем заменить /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 вернет <p>Who's looking for my-document.xml?</p>
.
Для любых других запросов мыпропустит их без выполнения переадресации или других действий с URL-адресом.
Если вы используете шаблонизатор HTML в eXist, вы, скорее всего, будете пересылать запросы в шаблон (document.html
) вместозапрос (doc.xq
).В этом случае директива становится немного сложнее немного :
<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>
переместилась во 2-ю директиву <forward>
.)
Другие внешние переменные (а именно, $exist:root
и $exist:prefix
) и другие виды директив (а именно, <redirect>
и другие подэлементы) описаны на странице документации eXist по перезаписи URL, http://exist -db.org / Существовать / приложения / doc / urlrewrite .Хотя страница в настоящее время предупреждает, что она устарела, я думаю, что это все еще хороший ресурс.
Сила средства перезаписи URL в eXist заключается в том, что вы можете использовать полную выразительность XQuery для определения того, как ваше приложение направляет и получает URL-адреса.Слабость в том, что контроллер может стать длинной цепочкой условных выражений, которые трудно поддерживать;просто постарайтесь сделать логику контроллера максимально простой.Изучение внешних переменных также может занять некоторое время;Я бы предложил широко использовать ведение журнала (с помощью функций util:log
или console:log
для вывода значений внешних переменных и другой информации о запросе, доступных через request:get-url()
и другие функции request:get-*
) дляПосмотрите, что происходит с каждым запросом, пока не получите его руку.Также может оказаться полезным изучить файлы контроллера в других приложениях, исходный код которых доступен, и задать дополнительные вопросы здесь!