gwt reverse-proxy

Problema con GWT detrás de un proxy inverso, ya sea nginx o apache



reverse-proxy (7)

La respuesta de KC es buena. Aquí hay una solución de código único para aquellos que no quieran jugar con las configuraciones de apache o que necesiten una forma rápida y sucia de realizar pruebas.

protected SerializationPolicy doGetSerializationPolicy(final HttpServletRequest request, String moduleBaseURL, final String strongName) { final String moduleBaseURLHdr = request.getHeader("X-GWT-Module-Base"); if (moduleBaseURLHdr != null) { moduleBaseURL = moduleBaseURLHdr.replace("foo/bar", "bar"); } return super.doGetSerializationPolicy(request, moduleBaseURL, strongName); }

La aplicación está en http://server/bar , el proxy la está sirviendo en http://proxy/foo/bar Por lo tanto, moduleBaseURL = moduleBaseURLHdr.replace ("foo / bar", "bar"); hace feliz a GWT Del mismo modo, si la aplicación está en http://server/bar y el proxy se está sirviendo en http://proxy/ , debe agregar una barra a moduleBaseURL (justo antes del nombre del paquete). Esto se puede generalizar mediante el uso de getServletContext (). GetContextPath () etc.

Estoy teniendo este problema con GWT cuando está detrás de un proxy inverso. La aplicación backend se implementa dentro de un contexto, llamémosla / context.

La aplicación GWT funciona bien cuando la golpeo directamente:

http://host:8080/context/

Puedo configurar un proxy inverso delante de él. Aquí está mi ejemplo nginx:

upstream backend { server 127.0.0.1:8080; } ... location / { proxy_pass http://backend/context/; }

Pero, cuando ejecuto el proxy inverso, GWT se confunde y dice:

2009-10-04 14:05:41.140:/:WARN: Login: ERROR: The serialization policy file ''/C7F5ECA5E3C10B453290DE47D3BE0F0E.gwt.rpc'' was not found; did you forget to include it in this deployment? 2009-10-04 14:05:41.140:/:WARN: Login: WARNING: Failed to get the SerializationPolicy ''C7F5ECA5E3C10B453290DE47D3BE0F0E'' for module ''https://hostname:444/''; a legacy, 1.3.3 compatible, serialization policy will be used. You may experience SerializationExceptions as a result. 2009-10-04 14:05:41.292:/:WARN: StoryService: ERROR: The serialization policy file ''/0445C2D48AEF2FB8CB70C4D4A7849D88.gwt.rpc'' was not found; did you forget to include it in this deployment? 2009-10-04 14:05:41.292:/:WARN: StoryService: WARNING: Failed to get the SerializationPolicy ''0445C2D48AEF2FB8CB70C4D4A7849D88'' for module ''https://hostname:444/''; a legacy, 1.3.3 compatible, serialization policy will be used. You may experience SerializationExceptions as a result.

En otras palabras, GWT no recibe la palabra que necesita anteponer / contexto / hen buscar C7F5ECA5E3C10B453290DE47D3BE0F0E.gwt.rpc, pero solo cuando la solicitud llega a través de un proxy. Una solución es agregar el contexto a la url para el sitio web:

location /context/ { proxy_pass http://backend/context/; }

pero eso significa que el contexto ahora es parte de la url que el usuario ve, y eso es feo.

¿Alguien sabe cómo hacer feliz a GWT en este caso?

Versiones de software:
GWT - 1.7.0 (mismo problema con 1.7.1)
Jetty - 6.1.21 (pero el mismo problema existía en Tomcat)
nginx - 0.7.62 (mismo problema bajo apache 2.x)

He examinado el tráfico entre el proxy y el backend utilizando DonsProxy , pero no hay nada digno de mención allí.


Me he encontrado con un problema similar, una solución exitosa fue hacer que todos los objetos serializados implementaran la interfaz IsSerializable de GWT (además de la interfaz Serializable estándar). Si lees el mensaje, indica que ''se utilizará una política de serialización heredada, compatible con 1.3.3''; la política compatible con 1.3.3 requiere que todos tus objetos serializados implementen la interfaz IsSerializable, así que al agregarlo, todo funcionó.

Me preocupa que la política heredada no se admita en futuras versiones de GWT, por lo que también estoy buscando una solución mejor para mí.


Mi objetivo era evitar encabezados adicionales que dificultarían la implementación y la configuración. Resolví este problema al anular RemoteServiceServlet.doGetSerializationPolicy() :

@Override protected SerializationPolicy doGetSerializationPolicy(HttpServletRequest request, String moduleBaseURL, String strongName) { String localServerAddress = "http://127.0.0.1:" + getThreadLocalRequest().getLocalPort(); String localContextPath = getServletConfig().getServletContext().getContextPath(); String moduleName = extractGwtModuleName(moduleBaseURL); String localModuleBaseURL = joinPaths(localServerAddress, localContextPath, moduleName, "/"); return super.doGetSerializationPolicy(request, localModuleBaseURL, strongName); }

En el código anterior:
extractGwtModuleName() extrae la última cadena prefijada y / o seguida de una barra
joinPaths() une varias partes de url, elimina barras innecesarias


Michele,

Gracias por el servlet de ejemplo para manejar este problema. Sin embargo, cuando intenté usar su enfoque, funcionó en el entorno de proxy inverso pero no en mi entorno de eclipse en modo dev.

Tomé un enfoque que me permitiría moverme sin problemas entre mis entornos dev y prod.

Como lo hizo, sobrescribí RemoteServiceServlet pero solo reemplacé el siguiente ...

@Override protected SerializationPolicy doGetSerializationPolicy( HttpServletRequest request, String moduleBaseURL, String strongName) { //get the base url from the header instead of the body this way //apache reverse proxy with rewrite on the header can work String moduleBaseURLHdr = request.getHeader("X-GWT-Module-Base"); if(moduleBaseURLHdr != null){ moduleBaseURL = moduleBaseURLHdr; } return super.doGetSerializationPolicy(request, moduleBaseURL, strongName); }

En mi configuración de apache he añadido ...

ProxyPass /app/ ajp://localhost:8009/App-0.0.1-SNAPSHOT/

RequestHeader edit X-GWT-Module-Base ^(.*)/app/(.*)$ $1/App-0.0.1-SNAPSHOT/$2

Este enfoque funciona en todos los escenarios y delega la url "mucking" a la configuración de proxy de Apache, que es el enfoque que siempre he tomado.

Se agradecen los comentarios sobre este enfoque.


Tengo el mismo problema, y ​​abrí un informe de error:

http://code.google.com/p/google-web-toolkit/issues/detail?id=4817

El problema es que estaba marcado "Como diseño", por lo que no creo que se solucione.

Encontré esta solución para mí. Extendí la clase RemoteServiceServlet y forcé a GWT a cargar el archivo de política de serialización a partir de ContextName en lugar de la URL. Luego extendí mi servicio mi clase en lugar de la clase RemoteServiceServlet. De esta manera, la aplicación se desvinculará de la URL desde donde se llamará.

Aquí está mi clase personalizada:

import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.text.ParseException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import com.google.gwt.user.server.rpc.RemoteServiceServlet; import com.google.gwt.user.server.rpc.SerializationPolicy; import com.google.gwt.user.server.rpc.SerializationPolicyLoader; public class MyRemoteServiceServlet extends RemoteServiceServlet { @Override protected SerializationPolicy doGetSerializationPolicy(HttpServletRequest request, String moduleBaseURL, String strongName) { return MyRemoteServiceServlet.loadSerializationPolicy(this, request, moduleBaseURL, strongName); } /** * Used by HybridServiceServlet. */ static SerializationPolicy loadSerializationPolicy(HttpServlet servlet, HttpServletRequest request, String moduleBaseURL, String strongName) { // The serialization policy path depends only by contraxt path String contextPath = request.getContextPath(); SerializationPolicy serializationPolicy = null; String contextRelativePath = contextPath + "/"; String serializationPolicyFilePath = SerializationPolicyLoader.getSerializationPolicyFileName(contextRelativePath + strongName); // Open the RPC resource file and read its contents. InputStream is = servlet.getServletContext().getResourceAsStream( serializationPolicyFilePath); try { if (is != null) { try { serializationPolicy = SerializationPolicyLoader.loadFromStream(is, null); } catch (ParseException e) { servlet.log("ERROR: Failed to parse the policy file ''" + serializationPolicyFilePath + "''", e); } catch (IOException e) { servlet.log("ERROR: Could not read the policy file ''" + serializationPolicyFilePath + "''", e); } } else { String message = "ERROR: The serialization policy file ''" + serializationPolicyFilePath + "'' was not found; did you forget to include it in this deployment?"; servlet.log(message); } } finally { if (is != null) { try { is.close(); } catch (IOException e) { // Ignore this error } } } return serializationPolicy; } }


Use JSON de descanso para sus llamadas RPC en lugar de GWT-RPC. Esto resuelve el problema del proxy inverso ya que no se requieren archivos de serialización.


Estoy bastante seguro de que la respuesta correcta aquí es parchear la fuente y enviar un informe de error. Otra opción sería ejecutar la aplicación GWT en / en su backend.

Prefiero lo primero, pero lo segundo debería funcionar también. Si realmente necesitaba cosas separadas en múltiples contextos, ¿usa un número de puerto diferente?