Jetty 9.x ProxyServlet-如何在XML中正确设置ServletContext

时间:2018-09-28 14:00:21

标签: xml configuration reverse-proxy jetty-9

旨在使用运行中的webapp servlet和代理servlet以及其他工具(如部署和控制台日志记录)在本地启动Jetty。所有Jetty配置都在XML文件中。

代理Servlet将GET前缀为/media/*的请求反向代理到外部站点https://example-server/。因此,http://localhost:8080/media/image.jpg将传递到https://media-server/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.xmlhttps://dzone.com/articles/configuring-jetty-servlet-proxy

改编而成的

从DZone指南中,我更新了Jetty 9.x的类名。因此,org.eclipse.jetty.servlets.ProxyServlet现在为org.eclipse.jetty.proxy.ProxyServlet,并且proxyToprefix参数必须以小写的p开头。

已检查jetty-proxy-9.4.12.v20180830.jar是否已包含在Jetty的启动配置中。

对于日志记录,Jetty命令行包含-Dorg.eclipse.jetty.proxy.LEVEL=DEBUG(我建议对其他对ProxyServlet进行故障排除的人使用。)

问题:没有任何反应。 ProxyServlet的{​​{1}}对“ http://localhost:8080/media/image.jpg”的请求未激活。

这是显示GET开始的日志行。

ServletContextHandler

我猜想有一个简单的解决方案,例如正确设置ServletContext,但是我不知道如何在XML中做到这一点,并且非常感谢您的帮助。码头documentation稀薄。

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

现在,如果我将更改为以下内容,则代理会对<http://localhost:8080/media/image.jpgjetty.xml请求进行 激活。

GET

日志显示ProxyServlet的激活方式如下:

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

但是这里代理失败,因为它具有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 上下文。因此将前缀(source code)设置为null是因为null/media为空。由于this source code,这将导致重定向到ServletContext.getContextPath()。将null设置为_prefix时,没有任何匹配的结果。可能是个错误,我已经开了一个问题。

2 个答案:

答案 0 :(得分:2)

这是在#include <stdio.h> #include <stdlib.h> /* append a character to a string, assuming s points to an array with enough space */ void append(char *s, char c) { size_t len = strlen(s); s[len] = c; s[len + 1] = '\0'; } int main(void) { int c; char *s; size_t i = 1; s = malloc(i * sizeof(char)); if (s == NULL) { printf("memory allocation failure\n"); return 1; } *s = '\0'; while ((c = getchar()) != EOF && c != '\n') { i++; s = realloc(s, i * sizeof(char)); if (s == NULL) { printf("memory allocation failure\n"); return 1; } append(s, c); } printf("%s\n", s); free(s); return 0; } 目录中使用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目录中查找webapp的配置并进行部署。

最后,将XML可部署程序设置为在${jetty.base}/webapps/ contextPath处有一个javax.servlet.ServletContext和一个已定义的servlet /,并带有一些初始参数。

答案 1 :(得分:1)

一种解决方法-并非完全是我想做的,但它确实有效-是从与Web应用程序关联的web.xml启动ProxyServlet。

<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库jar作为依赖项(版本必须与您的Jetty版本匹配),如下所示:

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

web.xml进行此操作与我在OP中希望通过Jetty自己的配置进行操作之间有一些区别。

  1. 代理URL现在必须采用以下形式(其中webapp是Webapp名称):http://localhost:8080/webapp/media/image.jpg
  2. Jetty版本更改时,Web应用程序必须更新web.xml-对于远程托管的应用程序可能是个问题
  3. 每个Web应用程序都必须包含此内容,而不是将其“内置”到Jetty中
  4. 与Jetty能够为不同的路径设置不同的servlet相比,这感觉不佳-这里的性能是否受到影响,因为代理的URL现在也已由webapp的过滤器进行了解析?
  5. 在代理请求周期完成时(可能需要测试...),可能会阻止webapp的线程