Problème avec GWT derrière un proxy inverse - Nginx ou apache

J'ai ce problème avec GWT quand il est derrière une procuration inversée. L'application backend est déployée dans un contexte - appelons-le /contexte.

Le GWT application fonctionne très bien quand j'ai frappé directement:

http://host:8080/context/

je peux configurer un proxy inverse devant elle. Voici mon exemple nginx:

upstream backend {
    server 127.0.0.1:8080;
}

...

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

mais, quand je cours à travers le mandataire inverse, GWT est confus, disant:

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.

Dans les autres mots, GWT n'est pas le mot qu'il a besoin d'ajouter /contexte/ poule recherchez C7F5ECA5E3C10B453290DE47D3BE0F0E.gwt.rpc, mais seulement lorsque la requête passe par procuration. Une solution consiste à ajouter le contexte de l'url du site web:

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

mais cela signifie que le contexte est maintenant une partie de l'url que l'utilisateur voit, et c'est laid.

Quelqu'un sait comment rendre GWT heureuse dans ce cas?

versions du logiciel:

GWT-1.7.0 (même problème avec 1.7.1)

La jetée - 6.1.21 (mais le même problème existait sous tomcat)

nginx-0.7.62 (même problème sous apache 2.x)

j'ai regardé le trafic entre le proxy et le serveur cible en utilisant DonsProxy, mais il n'y a rien de remarquable.

16
demandé sur Don Branson 2009-10-05 00:25:32

7 réponses

je suis assez sûr que la bonne réponse ici est de corriger la source et de soumettre un rapport de bogue. Une autre option serait de lancer L'application GWT à / sur votre backend.

je préférerais le premier, mais le second devrait fonctionner aussi. Si vous avez vraiment besoin de choses séparées en plusieurs contextes, utilisez un numéro de port différent?

3
répondu Bob Aman 2009-10-12 12:48:32

j'ai le même problème, et j'ai ouvert un rapport de bug:

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

le problème est qu'il a été marqué "en tant que Design", donc je ne pense pas qu'il sera corrigé.

j'ai trouvé cette solution pour moi. J'ai étendu la classe RemoteServiceServlet et j'ai forcé GWT à charger le fichier de politique de sérialisation à partir de ContextName au lieu de URL. Puis j'ai étendu mon service à ma classe au lieu de Classe RemoteServiceServlet. De cette façon, l'application sera déverrouillée de l'url d'où elle sera appelée.

voici ma classe personnalisée:

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;
      }
}
8
répondu Michele Renda 2010-05-01 21:19:28

Michele,

Merci pour l'exemple de servlet pour gérer ce problème. Cependant, lorsque j'ai essayé d'utiliser votre approche, cela a fonctionné dans l'environnement de proxy inverse mais pas dans mon environnement de mode dev eclipse.

j'ai adopté une approche qui me permettrait de me déplacer sans heurt entre mes environnements dev et prod.

comme vous l'avez fait, J'ai surpassé RemoteServiceServlet mais je n'ai remplacé que les suivants...

@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);
}

dans ma configuration apache ajouter...

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

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

cette approche fonctionne dans tous les scénarios et délègue l'url "mucking" aux paramètres de proxy d'apache qui est l'approche que j'ai toujours adoptée.

les Commentaires sur cette approche sont appréciés

7
répondu KC Berg 2010-09-22 16:22:19

j'ai rencontré un problème similaire, une solution réussie a été de faire en sorte que tous les objets sérialisés implémentent L'interface Isserialisable de GWT (en plus de L'interface sérialisable standard). Si vous lisez le message, il indique qu'une politique de sérialisation compatible avec 1.3.3 sera utilisée - la Politique compatible avec 1.3.3 exige que tous vos objets sérialisés implémentent L'interface Isserialisable, donc en l'ajoutant, tout a fonctionné.

je ne craint que le la Politique d'héritage sera abandonnée dans les versions futures de GWT, donc je suis aussi à la recherche d'une meilleure solution de contournement moi-même.

2
répondu Chi 2009-10-04 20:52:14

la réponse de KC est bonne. Pour ceux qui ne veulent pas se faufiler avec apache configs, ou ont besoin d'un moyen rapide et sale de tester, voici une solution de code seulement.

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);
}

L'application est sur http://server/bar, le proxy est de le servir à http://proxy/foo/bar D'où moduleBaseURL = moduleBaseURLHdr.remplacer ("foo / bar", "bar"); rend GWT heureux. De même, si l'application est à http://server/bar et le proxy est en service à http://proxy/, vous devez ajouter la barre au moduleBaseURL (juste avant le paquet nom.) Ceci peut être généralisé par l'utilisation de getServletContext().getContextPath () etc...

2
répondu Tony BenBrahim 2012-05-27 21:54:29

mon but était d'éviter les en-têtes supplémentaires qui rendraient le déploiement et la configuration plus difficiles. J'ai résolu ce problème en remplaçant 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);
    }

dans le code ci-dessus:

extractGwtModuleName() extraits de la dernière chaîne préfixée et / ou suivie de slash

joinPaths() joint plusieurs parties d'url, supprime les slashes inutiles

1
répondu JafarSadik 2014-07-29 21:26:28

utilisez restful JSON pour vos appels RPC au lieu de GWT-RPC. Cela résout le problème du mandataire inversé puisqu'aucun fichier de sérialisation n'est requis.

0
répondu jasop 2012-08-03 14:16:06