16

GWT がリバース プロキシの背後にある場合、GWT でこの問題が発生します。バックエンド アプリはコンテキスト内にデプロイされます。これを /context と呼びましょう。

直接ヒットすると、GWT アプリは正常に動作します。

http://ホスト:8080/context/

その前にリバース プロキシを構成できます。これが私のnginxの例です:

アップストリーム バックエンド {
    サーバー 127.0.0.1:8080;
}

...

位置 / {
   proxy_pass http://backend/context/;
}

しかし、リバース プロキシを介して実行すると、GWT は次のように混乱します。

2009-10-04 14:05:41.140:/:警告: ログイン: エラー: シリアル化ポリシー ファイル '/C7F5ECA5E3C10B453290DE47D3BE0F0E.gwt.rpc' が見つかりませんでした。この展開に含めるのを忘れましたか?
2009-10-04 14:05:41.140:/:警告: ログイン: 警告: モジュール 'https://hostname:444/' の SerializationPolicy 'C7F5ECA5E3C10B453290DE47D3BE0F0E' の取得に失敗しました。従来の 1.3.3 互換のシリアル化ポリシーが使用されます。その結果、SerializationExceptions が発生する場合があります。
2009-10-04 14:05:41.292:/:WARN: StoryService: エラー: シリアル化ポリシー ファイル '/0445C2D48AEF2FB8CB70C4D4A7849D88.gwt.rpc' が見つかりませんでした。この展開に含めるのを忘れましたか?
2009-10-04 14:05:41.292:/:WARN: StoryService: 警告: モジュール 'https://hostname:444/' の SerializationPolicy '0445C2D48AEF2FB8CB70C4D4A7849D88' の取得に失敗しました。従来の 1.3.3 互換のシリアル化ポリシーが使用されます。その結果、SerializationExceptions が発生する場合があります。

言い換えれば、GWT は /context/ を前に追加して C7F5ECA5E3C10B453290DE47D3BE0F0E.gwt.rpc を探す必要があるという言葉を受け取っていませんが、それは要求がプロキシ経由で来た場合のみです。回避策は、Web サイトの URL にコンテキストを追加することです。

場所/コンテキスト/ {
    proxy_pass http://backend/context/;
}

しかし、これはコンテキストがユーザーに表示される URL の一部になっていることを意味し、これは醜いことです。

この場合、GWTを幸せにする方法を知っている人はいますか?

ソフトウェア バージョン:
GWT - 1.7.0 (1.7.1 と同じ問題)
Jetty - 6.1.21 (ただし、Tomcat にも同じ問題が存在)
nginx - 0.7.62 (Apache 2.x にも同じ問題)

DonsProxyを使用してプロキシとバックエンドの間のトラフィックを確認しましたが、特筆すべき点はありません。

4

7 に答える 7

9

同じ問題があり、バグレポートを開きました。

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

問題は「デザインとして」とマークされていたので、修正されるとは思いません。

私は私のためにこの解決策を見つけました。クラスRemoteServiceServletを拡張し、GWTにURLではなくContextNameから始まるシリアル化ポリシーファイルをロードするように強制しました。次に、RemoteServiceServletクラスの代わりに自分のクラスでサービスを拡張しました。このようにして、アプリケーションは、呼び出されるURLからリンク解除されます。

これが私のカスタムクラスです:

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;
      }
}
于 2010-05-01T16:40:04.590 に答える
7

ミケーレ、

この問題を処理するサーブレットの例をありがとう。ただし、あなたのアプローチを使用しようとすると、リバース プロキシ環境では機能しましたが、開発モードの Eclipse 環境では機能しませんでした。

私は、開発環境と本番環境の間をシームレスに移動できるアプローチを取りました。

あなたがしたように、私は RemoteServiceServlet を上書きしましたが、次のものだけを置き換えました...

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

私のApache設定で追加しました...

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

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

このアプローチはすべてのシナリオで機能し、URL「マッキング」をApacheのプロキシ設定に委任します。これは私が常に取ってきたアプローチです。

このアプローチに関するコメントを歓迎します

于 2010-09-22T16:22:19.167 に答える
3

ここでの正解は、ソースにパッチを適用してバグレポートを送信することだと確信しています。/もう1つのオプションは、バックエンドでGWTアプリを実行することです。

前者の方がいいのですが、後者でもうまくいくはずです。複数のコンテキストに分割する必要がある場合は、別のポート番号を使用しますか?

于 2009-10-12T12:48:32.163 に答える
2

KCの答えは良いです。Apache の設定をいじりたくない人や、手早く面倒なテスト方法が必要な人のために、ここにコードのみのソリューションがあります。

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

アプリケーションは onhttp://server/barで、プロキシはそれを提供していhttp://proxy/foo/bar ます。GWTを幸せにします。同様に、アプリケーションが にhttp://server/barあり、プロキシが にあるhttp://proxy/場合、bar を moduleBaseURL (パッケージ名の直前) に追加する必要があります。これは、getServletContext().getContextPath() などを使用して一般化できます...

于 2012-05-27T21:54:29.893 に答える
0

GWT-RPCの代わりに、RPC呼び出しにRESTfulJSONを使用します。これにより、シリアル化ファイルが不要になるため、リバースプロキシの問題が解決されます。

于 2012-08-03T14:16:06.040 に答える