反向代理背后的GWT存在问题-nginx或apache
当GWT位于反向代理之后时,我遇到了这个问题。后端应用程序部署在上下文中,我们称之为/context 当我直接点击GWT应用程序时,它工作正常: 我可以在它前面配置一个反向代理。以下是我的nginx示例: upstream backend { server 127.0.0.1:8080; } ... location / { proxy_pass http://backend/context/; } 上游后端{ 服务器127.0.0.1:8080; } ... 地点/{ 代理通行证http://backend/context/; } 但是,当我运行反向代理时,GWT感到困惑,说: 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. 2009-10-04 14:05:41.140:/:警告:登录:错误:找不到序列化策略文件“/C7F5ECA5E3C10B453290DE47D3BE0F0E.gwt.rpc”;您是否忘记将其包含在此部署中? 2009-10-04 14:05:41.140:/:警告:登录:警告:无法获取模块的序列化策略“C7F5ECA5E3C10B453290DE47D3BE0F0E”https://hostname:444/'; 将使用与1.3.3兼容的传统序列化策略。因此,您可能会遇到序列化异常。 2009-10-04 14:05:41.292:/:警告:StoryService:错误:找不到序列化策略文件“/0445C2D48AEF2FB8CB70C4D4A7849D88.gwt.rpc”;您是否忘记将其包含在此部署中? 2009-10-04 14:05:41.292:/:警告:故事服务:警告:无法获取模块的序列化策略“0445C2D48AEF2FB8CB70C4D4A7849D88”https://hostname:444/'; 将使用与1.3.3兼容的传统序列化策略。因此,您可能会遇到序列化异常。 换句话说,GWT没有得到查找C7F5ECA5E3C10B453290DE47D3BE0F0E.GWT.rpc所需的前置词/context/hen,但仅当请求通过代理到达时。解决方法是将上下文添加到网站的url: location /context/ { proxy_pass http://backend/context/; } 地点/背景/{ 代理通行证http://backend/context/; } 但这意味着上下文现在是用户看到的url的一部分,这很难看 有人知道在这种情况下如何让GWT开心吗 软件版本:反向代理背后的GWT存在问题-nginx或apache,gwt,reverse-proxy,Gwt,Reverse Proxy,当GWT位于反向代理之后时,我遇到了这个问题。后端应用程序部署在上下文中,我们称之为/context 当我直接点击GWT应用程序时,它工作正常: 我可以在它前面配置一个反向代理。以下是我的nginx示例: upstream backend { server 127.0.0.1:8080; } ... location / { proxy_pass http://backend/context/; } 上游后端{ 服务器127.0.0.1:8080; } ...
GWT-1.7.0(与1.7.1的问题相同)
Jetty-6.1.21(但tomcat下也存在同样的问题)
nginx-0.7.62(在Apache2.x下存在相同的问题)
我已经使用查看了代理和后端之间的通信量,但是没有什么值得注意的。我遇到了类似的问题,一个成功的解决方法是让所有序列化对象实现GWT的IsSerializable接口(除了标准的Serializable接口)。如果您阅读该消息,它会声明“将使用与1.3.3兼容的旧版序列化策略”-1.3.3兼容策略要求所有序列化对象实现IsSerializable接口,因此通过添加它,一切都正常
我确实担心遗留策略将在未来版本的GWT中被取消支持,因此我自己也在寻找更好的解决方法。我确信正确的答案是修补源代码并提交错误报告。另一个选项是在后端运行GWT应用程序
我更喜欢前者,但后者也行。如果您确实需要将内容分为多个上下文,请使用不同的端口号?我也有同样的问题,我打开了一个错误报告: 问题是它被标记为“设计”,所以我认为它不会被修复 我找到了这个解决方案。我扩展了RemoteServiceServlet类,并强制GWT从ContextName而不是URL加载序列化策略文件。 然后,我将服务扩展到我的类,而不是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;
}
}
米歇尔
感谢您提供处理此问题的示例servlet。然而,当我尝试使用您的方法时,它在反向代理环境中有效,但在我的开发模式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/
这种方法适用于所有场景,并将url“mucking”委托给apache的代理设置,这是我一直采用的方法
对这种方法的评论非常感谢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);
}
应用程序已打开http://server/bar
,代理服务器在http://proxy/foo/bar
因此moduleBaseURL=moduleBaseURLHdr.replace(“foo/bar”、“bar”);让GWT开心。
同样,如果应用程序位于http://server/bar
并且代理服务器在http://proxy/
,您需要向moduleBaseURL添加条(就在包名称之前)。
这可以通过使用getServletContext().getContextPath()等来概括。对RPC调用使用restful JSON,而不是GWT-RPC。
这解决了反向代理问题,因为不需要序列化文件。我的目标是避免额外的头,这将使部署和配置更加困难。我通过重写
RemoteServiceServlet.doGetSerializationPolicy()
解决了这个问题:
@凌驾
受保护的序列化策略doGetSerializationPolicy(HttpServletRequest请求,字符串moduleBaseURL,字符串strongName){
字符串localServerAddress=”http://127.0.0.1:“+getThreadLocalRequest().getLocalPort();
字符串localContextPath=getServletConfig().getServletContext().getContextPath();
字符串moduleName=extractGwtModuleName(moduleBaseURL);
字符串localModuleBaseURL=joinPath(localServerAddress、localContextPath、moduleName,“/”;
返回super.doGetSerializationPolicy(请求、localModuleBaseURL、strongName);
}
在上述代码中:extractGwtModuleName()
ext
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);
}
@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);
}