Reenvío de solicitudes entre contextos en Tomcat

Me gustaría poder realizar el reenvío de solicitudes de contexto cruzado en Tomcat con el filtro Tuckey URLRewrite. Por ejemplo, me gustaría poder enrutar una solicitud entrante con una URL amigable para SEO/usuario como http://example.com/group-elements/300245/some-descriptive-text, donde "elementos de grupo" no es el nombre de una aplicación implementada, a una URL asignada a un método de controlador de Java Spring para la aplicación 'foo', como http://example.com/foo/app/group/300245/elements. Estoy usando Tomcat 7.0.27 y URLRewrite 3.2.0; Estoy trabajando con aplicaciones web Java Spring 3.1.

La Documentación de URLRewrite 3.20 señala un atributo de 'contexto' opcional para el elemento de parámetro de filtro 'a':

If your application server is configured to allow "cross context" communication then this attribute can be used to forward (and only forward, not redirect or other "to" types) requests to a named servlet context.

On Tomcat, for instance, the application contexts in the server configuration (server.xml or context.xml) need the option crossContext="true". For instance, the two applications mentioned before ("app" and "forum") have to be defined as:

<Context docBase="app" path="/app" reloadable="true" crossContext="true"/>
<Context docBase="forum" path="/forum" reloadable="true" crossContext="true"/>

Dado eso y el discusión original sobre la característica, el atributo 'contexto' parece ser lo que estoy buscando. Sin embargo, no he podido habilitar correctamente el reenvío de solicitudes entre contextos.

Aquí está mi aplicación de entrada de 'Contexto' 'foo' en conf/server.xml:

<Context docBase="foo" path="/foo" reloadable="true" crossContext="true"/>

Tengo mi archivo urlrewrite.xml y web.xml en webapps/ROOT/WEB-INF/. Así es como se ven:

urlrewrite.xml:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 3.2//EN" 
"http://tuckey.org/res/dtds/urlrewrite3.2.dtd">

<urlrewrite>    
    <rule>
        <from>baz</from>
        <!-- Note: this 'to' element's value has an error.  See the edit at bottom of this post for corrected version. -->
        <to context="foo">/foo/app/group/300245/elements</to> 
    </rule> 
</urlrewrite>

web.xml:

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_5.xsd" version="2.5">

    <filter>
        <filter-name>UrlRewriteFilter</filter-name>
        <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
        <init-param>
            <param-name>logLevel</param-name>
            <param-value>WARN</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>UrlRewriteFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

</web-app>

La regla definida anteriormente en urlrewrite.xml es intencionalmente básica y codificada. En este caso, simplemente estoy tratando de hacer funcionar el aspecto de contexto cruzado de la regla antes de desarrollar las expresiones regulares en 'to' y 'from'.

Cuando solicito http://example.com/baz con esa regla en vigor, Tomcat devuelve un error 404 que dice "El recurso solicitado (/baz) no está disponible". He probado algunas variaciones en el parámetro de filtro 'a', pero nada ha funcionado todavía. Y no he podido encontrar ningún ejemplo de cómo se debe usar 'contexto'.

¿Alguna idea sobre cómo podría hacer funcionar este tipo de filtrado de solicitudes de contexto cruzado? ¿Es posible? Me imagino que podría lograr lo que estoy tratando de hacer cambiando el nombre de foo.war a ROOT.war o cambiando la aplicación raíz como se mencionó aquí, pero me gustaría intentar hacer esto a través de URLRewrite a menos que hacerlo no sea factible o sea una mala idea.

Si mostrar más de mi configuración ayudaría, por favor hágamelo saber. Gracias por adelantado por cualquier contribución.

Editar:

Gracias a Christopher Schultz por la útil respuesta. En mi caso, el problema fue causado por dos cosas: 1) no tener un archivo context.xml en webapps/ROOT/META-INF, y 2) tener un error en el elemento 'to' en la regla de reescritura de URL en webapps/ RAÍZ/WEB-INF/urlrewrite.xml.

La solución implicó colocar un archivo context.xml adecuado en webapps/ROOT/META-INF. Como referencia para cualquier otra persona que encuentre este problema, ese archivo terminó luciendo así:

webapps/ROOT/META-INF/context.xml

<?xml version='1.0' encoding='utf-8'?>

<Context docBase="ROOT" path="/" reloadable="true" crossContext="true" />

Como menciona Schultz, solo es necesario que se defina un contexto con crossContext="true" para el contexto implícito en el elemento 'from' en una regla de reescritura de URL dada (aquí, eso es ROOT). No es necesario definir explícitamente un contexto para la aplicación en la regla de reescritura de URL 'a'. En otras palabras, no debería necesitar crear manualmente un archivo context.xml para esa aplicación; por lo tanto, continuando con el ejemplo anterior, no necesitaría definir y colocar manualmente un archivo context.xml en webapps/foo/META-INF. /.

La respuesta de Schultz refleja las recomendaciones para definir un contexto en la documentación oficial de Tomcat: http://tomcat.apache.org/tomcat-7.0-doc/config/context.html#Defining_a_context.

El problema también fue causado por el hecho de que la regla de reescritura de URL en mi publicación inicial tenía un error. La versión correcta debería haber sido:

urlrewrite.xml:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 3.2//EN" 
"http://tuckey.org/res/dtds/urlrewrite3.2.dtd">

<urlrewrite>    
    <rule>
        <from>baz</from>
        <!-- Note: the use of '/app' instead of '/foo/app/' below -->
        <to context="foo">/app/group/300245/elements</to> 
    </rule> 
</urlrewrite>

preguntado el 12 de junio de 12 a las 18:06

Tal vez sea una pregunta estúpida, pero ¿su URL funciona sin nada sobre el contexto cruzado en su aplicación? -

Si entiendo bien tu pregunta, no. La URL amigable para SEO/usuario actualmente no se asigna a nada y produce un 404. -

¿Por qué esperas algo más que un 404 con contexto cruzado si ya tienes un 404 sin contexto cruzado? -

Porque estoy tratando de asignar la URL fácil de usar que se dirige al contexto raíz (donde no se implementa nada) al contexto de una aplicación implementada, preferiblemente con URLRewrite. -

¿Dónde está realmente su aplicación web en el disco? De acuerdo a tu <Context>, la aplicación está en $CATALINA_BASE/foo. -

2 Respuestas

Si su aplicación web (real) se implementa en /foo y desea reescribir URL sobre la marcha como /group-elements/baz reenviar (no redirigir a /foo/app/group/300245/elements, entonces tendrá que implementar su filtro de reescritura en uno de dos lugares: /group-elements or /.

La configuración anterior parece implementarse en ROOT (que is /) pero luego asignando la URL /baz a /foo/app/group/300245/elements. En su lugar, probablemente quieras esto:

<rule>
    <from>/group-elements/baz</from>
    <to context="foo">/foo/app/group/300245/elements</to>
</rule>

Se parece a ti tuvieron tratando de golpear http://example.com/baz que hubiera esperado que funcionara. La última pizca de magia va a ser hacer que el ROOT contexto de contexto cruzado (tenga en cuenta que su aplicación web NO necesita ser de contexto cruzado: solo el urlrewrite lo hace). Puedes cambiar el ROOT aplicación web para ser de contexto cruzado por addint crossContext="true" a webapps/ROOT/META-INF/context.xml.

Finalmente, realmente deberías dejar de poner <Context> elementos en server.xml: dejarlos allí básicamente significa que necesita reiniciar Tomcat para cambiar las implementaciones de su aplicación web.

Respondido el 12 de junio de 12 a las 21:06

Gracias, el enfoque en la respuesta anterior funciona bien. En mi caso, la pieza clave aquí fue definir el elemento en webapps/ROOT/META-INF/context.xml. - jqp

Ah, y una corrección para la sintaxis de 'regla' en el ejemplo de código anterior: el segmento "/foo/app" en el valor del elemento 'to' es incorrecto; debería ser simplemente "/app", es decir /aplicación/grupo/300245/elementos . - jqp

Después de los comentarios vengo a hacer esta posible conclusión:

Creo que está mezclando los conceptos de un proxy inverso con contexto cruzado. El contexto cruzado es un método para compartir datos entre dos aplicaciones web dentro del mismo servidor de aplicaciones. Un proxy inverso como 'Apache http' puede reescribir una URL para pasarla a un determinado servidor detrás de ella, ocultando efectivamente cualquier parte no deseada o realizando otras operaciones como el equilibrio de carga.

La infraestructura sería: cliente --> proxy inverso --> servidor de aplicaciones

Respondido el 12 de junio de 12 a las 19:06

¿No es 'ROOT' todavía un contexto en Tomcat, a pesar de que no tiene una aplicación convencional implementada? ¿En qué se diferencia significativamente el caso de uso que describo del descrito en el parche inicial de la función? aquí? Podría estar perdiéndome algo en mi lectura, pero el uso inicial del parche parece que no se estaba reenviando de una aplicación web implementada a otra aplicación web implementada, ¿o sí? - jqp

Creo que si desea usar ese filtro, debe implementar una aplicación con ese filtro en la RAÍZ. Si no lo hace, no habrá nadie escuchando en esa URL, por lo que no pasará nada, excepto un 404. Tomcat no es mágico. Solo hace lo que le dices que haga. - tom

Creo que vale la pena seguir aquí para mencionar que la infraestructura 'cliente --> proxy inverso --> aplicación' parece una posible opción para habilitar lo que estoy tratando de hacer, pero no es necesario. Es posible realizar el reenvío entre contextos solo en Tomcat, utilizando el enfoque mencionado en la respuesta de Schultz. Una posible confusión en la terminología (al menos por mi parte) podría haber contribuido a cierta confusión aquí. - jqp

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.