Jetty 9.x ProxyServlet - как правильно настроить ServletContext в XML - PullRequest
0 голосов
/ 28 сентября 2018

Стремление запустить Jetty локально с запущенным сервлетом веб-приложения и сервлетом-посредником, а также другими инструментами, такими как развертывание и ведение журнала консоли.Вся конфигурация Jetty находится в XML-файлах.

Прокси-сервлет обратный прокси-сервер GET запросов с префиксом /media/* на внешний сайт https://example-server/.Так что http://localhost:8080/media/image.jpg перейдет на https://media -сервер / image.jpg .

Вот выдержка из моего jetty.xml:

<Set name="handler">
  <New id="Handlers" class="org.eclipse.jetty.server.handler.HandlerCollection">
    <Set name="handlers">
     <Array type="org.eclipse.jetty.server.Handler">
       <Item>
         <New id="Contexts" class="org.eclipse.jetty.server.handler.ContextHandlerCollection"/>
       </Item>
       <Item>
         <New id="context" class="org.eclipse.jetty.servlet.ServletContextHandler">
           <Arg><Get class="org.eclipse.jetty.servlet.ServletContextHandler" name="SESSIONS"/></Arg>
           <Call name="setContextPath" arg="/"/>
           <Set name="servletHandler">
             <New id="handler" class="org.eclipse.jetty.servlet.ServletHandler">
               <Call id="holder" name="addServletWithMapping" arg="org.eclipse.jetty.proxy.ProxyServlet$Transparent,/media/*">
                 <Call name="setInitParameter" arg="proxyTo,https://media-server"/>
                 <Call name="setInitParameter" arg="prefix,/media"/>
               </Call>
             </New>
           </Set>
         </New>
       </Item>
       <Item>
         <New id="DefaultHandler" class="org.eclipse.jetty.server.handler.DefaultHandler"/>
       </Item>
     </Array>
    </Set>
  </New>
</Set>

Приведенный выше XML должен быть эквивалентен этому Java-коду.

ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");
ServletHandler handler = new ServletHandler();
ServletHolder holder = handler.addServletWithMapping(ProxyServlet$Transparent.class, "/media/*");
holder.setInitParameter("proxyTo", "https://media-server");
holder.setInitParameter("prefix", "/media");
context.setServletHandler(handler);

Это адаптировано из значений по умолчанию jetty.xml и https://dzone.com/articles/configuring-jetty-servlet-proxy

Из руководства по DZone я обновил классназвания для Jetty 9.x.Таким образом, org.eclipse.jetty.servlets.ProxyServlet теперь org.eclipse.jetty.proxy.ProxyServlet, а параметры proxyTo и prefix должны начинаться со строчной буквы p.

. Проверено, что jetty-proxy-9.4.12.v20180830.jar включена в качестве библиотеки в конфигурации запуска Jetty.

Для ведения журнала командная строка Jetty включает -Dorg.eclipse.jetty.proxy.LEVEL=DEBUG (я рекомендую это для устранения неполадок ProxyServlet.)

Проблема: ничего не происходит.ProxyServlet не активируется на GET запросах к `http://localhost:8080/media/image.jpg'.

Вот строка журнала, показывающая, что ServletContextHandler запускается.

2018-09-28 15:26:46.045:INFO:oejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@1e028a9{"",null,AVAILABLE}

Я думаю, что естьЭто простое решение, например, правильная настройка ServletContext, но я не могу понять, как это сделать в XML, и буду очень признателен за помощь.Jetty документация на это тонкая.

Теперь, если я изменю jetty.xml на это ниже, то прокси делает активировать на GET запросы к `http://localhost:8080/media/image.jpg'.

<Set name="handler">
  <New id="Handlers" class="org.eclipse.jetty.server.handler.HandlerCollection">
    <Set name="handlers">
     <Array type="org.eclipse.jetty.server.Handler">
       <Item>
         <New id="Contexts" class="org.eclipse.jetty.server.handler.ContextHandlerCollection"/>
       </Item>
       <Item>
         <New id="handler" class="org.eclipse.jetty.servlet.ServletHandler">
           <Call id="holder" name="addServletWithMapping" arg="org.eclipse.jetty.proxy.ProxyServlet$Transparent,/media/*">
             <Call name="setInitParameter" arg="proxyTo,https://media-server"/>
             <Call name="setInitParameter" arg="prefix,/media"/>
           </Call>
         </New>
       </Item>
       <Item>
         <New id="DefaultHandler" class="org.eclipse.jetty.server.handler.DefaultHandler"/>
       </Item>
     </Array>
    </Set>
  </New>
</Set>

В журнале показано, как ProxyServlet активируется следующим образом:

2018-09-28 14:22:14.904:DBUG:oejpP.194a1b5:qtp22374712-13: org.eclipse.jetty.proxy.ProxyServlet$Transparent-194a1b5 @ null/media to https://media-server
2018-09-28 14:22:14.904:DBUG:oejpP.194a1b5:qtp22374712-13: 21964987 rewriting: http://localhost:8080/media/image.jpg -> null

Но здесь прокси не работает, потому что у него1072 * контекст.Таким образом, префикс был установлен ( исходный код ) на null/media, потому что ServletContext.getContextPath() равен нулю.И это вызывает перенаправление на null из-за этого исходного кода _prefix, установленным на null/media, ничто не сравнится с этим.Возможно, это ошибка, я открыл проблему.

Ответы [ 2 ]

0 голосов
/ 01 октября 2018

Вот пример использования ProxyServlet из каталога ${jetty.base}.

$ mkdir proxy-example-base
$ cd proxy-example-base/
$ java -jar ../../jetty-home-9.4.12.v20180830/start.jar --add-to-start=http,deploy,proxy
INFO  : webapp          transitively enabled, ini template available with --add-to-start=webapp
INFO  : server          transitively enabled, ini template available with --add-to-start=server
INFO  : proxy           initialized in ${jetty.base}/start.ini
INFO  : security        transitively enabled
INFO  : servlet         transitively enabled
INFO  : http            initialized in ${jetty.base}/start.ini
INFO  : client          transitively enabled
INFO  : threadpool      transitively enabled, ini template available with --add-to-start=threadpool
INFO  : deploy          initialized in ${jetty.base}/start.ini
MKDIR : ${jetty.base}/webapps
INFO  : Base directory was modified
$ ls -la
total 8
drwxr-xr-x   4 joakim  staff   136 Oct  1 14:10 ./
drwxr-xr-x  17 joakim  staff   578 Oct  1 14:10 ../
-rw-r--r--   1 joakim  staff  2146 Oct  1 14:10 start.ini
drwxr-xr-x   3 joakim  staff   102 Oct  1 14:11 webapps/
$ cp ~/Downloads/media-proxy.xml webapps/
$ cat webapps/media-proxy.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<Configure class="org.eclipse.jetty.servlet.ServletContextHandler">
  <Set name="contextPath">/</Set>
  <Call name="addServlet">
    <Arg>org.eclipse.jetty.proxy.ProxyServlet$Transparent.class</Arg>
    <Arg>/media/*</Arg>
    <Set name="InitOrder">1</Set>
    <Call name="setInitParameter">
      <Arg>proxyTo</Arg>
      <Arg>https://media-server/</Arg>
    </Call>
    <Call name="setInitParameter">
      <Arg>prefix</Arg>
      <Arg>/media</Arg>
    </Call>
  </Call>
</Configure>

Способ, которым это работает, заключается в том, что ${jetty.base} настроен на включение модуля пристани proxy, которыйпомещает прокси-классы в путь к классам сервера.

Затем включается модуль deploy jetty для поиска конфигураций веб-приложений в каталоге ${jetty.base}/webapps/ и их развертывания.

Наконец, развертываемый XMLнастроен так, чтобы иметь javax.servlet.ServletContext в / contextPath и один определенный сервлет, ProxyServlet$Transparent с некоторыми параметрами init.

0 голосов
/ 29 сентября 2018

Одно из возможных решений - не совсем то, что я хотел сделать, но оно работает - это запуск ProxyServlet из web.xml, связанного с веб-приложением.

<servlet>
  <servlet-name>JettyProxy</servlet-name>
  <servlet-class>org.eclipse.jetty.proxy.ProxyServlet$Transparent</servlet-class>
  <init-param>
    <param-name>proxyTo</param-name>
    <param-value>https://media-server</param-value>
  </init-param>
  <init-param>
    <param-name>prefix</param-name>
    <param-value>/media</param-value>
  </init-param>
  <load-on-startup>1</load-on-startup>
  <async-supported>true</async-supported>
</servlet>
<servlet-mapping>
  <servlet-name>JettyProxy</servlet-name>
  <url-pattern>/media/*</url-pattern>
</servlet-mapping>

Дополнительные ошибки:

  • Любые фильтры, определенные в вашем web.xml, теперь также нуждаются в <async-supported>true</async-supported> строке
  • Теперь ваш проект требует библиотечный файл jetty-proxy в качестве зависимости (версия должна соответствовать вашей версии Jetty), например:

    <dependency>
       <groupId>org.eclipse.jetty</groupId>
      <artifactId>jetty-proxy</artifactId>
      <version>9.4.12.v20180830</version>
    </dependency>
    

Существует несколько отличий между выполнением этого способа из web.xml и выполнением его из собственной конфигурации Jetty, когда яхотел сделать в OP.

  1. URL-адреса прокси должны теперь быть в этой форме (где webapp - имя веб-приложения): http://localhost:8080/webapp/media/image.jpg
  2. веб-приложение должно обновлять web.xmlкогда изменяется версия Jetty - это может быть проблемой для приложений, размещенных на удаленном хосте
  3. , каждое веб-приложение должно включать это, вместо того, чтобы быть "встроенным" в Jetty
  4. , оно выглядит не элегантным по сравнению с настройкой различныхсервлеты по разным путямs Jetty способен - есть ли здесь снижение производительности, потому что прокси-URL-адреса теперь также анализируются фильтрами веб-приложения?
  5. возможная блокировка потоков веб-приложения, пока завершается цикл запроса прокси-сервера (требуется тестирование ...)
...