为什么像中文和丹麦语这样的非 ASCII 字符在 Tomcat 8 Url 重写中被破坏?
Why are non-ASCII charcters like chinese and danish getting mangled in Tomcat 8 Url Rewrite?
我正在将 URL 重写功能从 Apache mod_rewrite 迁移到 Tomcat 8 的 RewriteValve。有一些规则,例如
RewriteRule ^/abc/(.*)$ /xyz.do?param= [L]
重写的 URL 不适用于中文和其他此类非 ASCII 字符。检查重写日志,我发现 URL 重写工作正常。在访问日志中,非 ASCII 字符打印为问号字符。但是这些 URL 与 Apache 的 mod_rewrite.
一起工作得很好
实际URL是http://www.example.com/abc/在线测试
重写日志
Rewrote /abc/在线测试 as /xyz.do?param=在线测试 with rule pattern ^/abc/(.*)$
访问日志
/xyz.do?param=????
编辑
进一步调试我发现这种行为只适用于查询字符串。我正在使用 Tomcat 8.0.35.
rewrite.config 文件
RewriteRule ^/abc/(.*)$ /xyz? [L]
RewriteRule ^/test/(.*)/(. *)$ /test/? [L]
我添加了一个自定义记录阀
public class CustomValve extends ValveBase {
private static final Logger logger = Logger.getLogger(CustomValve.class.getName());
public void invoke(Request request, Response response) throws IOException, ServletException {
HttpServletRequest httpServletRequest = request.getRequest();
String contextPath = request.getRequestURI();
logger.log(Level.SEVERE, "Context Path: "+contextPath);
String queryString = request.getQueryString();
if(queryString != null)
{
logger.log(Level.SEVERE, "QueryString: "+request.getQueryString());
}
else
{
logger.log(Level.INFO, "QueryString: Null");
}
getNext().invoke(request, response);
}
}
此记录阀配置有重写阀
context.xml
<Context>
<Valve className="org.apache.catalina.valves.rewrite.RewriteValve"/>
<Valve className="com.logging.valves.CustomValve"/>
</Context>
URL 访问过
http://localhost:8080/test/在线测试/在线测试
已记录自定义记录器
上下文路径:/test/%E5%9C%A8%E7%BA%BF%E6%B5%8B%E8%AF%95
QueryString: 在线测试
访问日志
/test/%E5%9C%A8%E7%BA%BF%E6%B5%8B%E8%AF%95????
请求 URI 中的非 ASCII 字符已编码,但查询字符串仍未编码。检查 Tomcat 的 RewriteValve 的实现,我发现请求 URI 已编码。
request.getCoyoteRequest().requestURI().setString(null);
CharChunk chunk = request.getCoyoteRequest().requestURI().getCharChunk();
chunk.recycle();
if (this.context) {
chunk.append(contextPath);
}
//encoding of request URI
chunk.append(URLEncoder.DEFAULT.encode(urlString));
request.getCoyoteRequest().requestURI().toChars();
但是查询字符串没有这样的编码
if (queryString != null) {
request.getCoyoteRequest().queryString().setString(null);
chunk = request.getCoyoteRequest().queryString().getCharChunk();
chunk.recycle();
chunk.append(queryString);
request.getCoyoteRequest().queryString().toChars();
}
有没有办法解决这个问题?
似乎是 RewriteValve 实现中的错误。
我正在将 URL 重写功能从 Apache mod_rewrite 迁移到 Tomcat 8 的 RewriteValve。有一些规则,例如
RewriteRule ^/abc/(.*)$ /xyz.do?param= [L]
重写的 URL 不适用于中文和其他此类非 ASCII 字符。检查重写日志,我发现 URL 重写工作正常。在访问日志中,非 ASCII 字符打印为问号字符。但是这些 URL 与 Apache 的 mod_rewrite.
一起工作得很好实际URL是http://www.example.com/abc/在线测试
重写日志
Rewrote /abc/在线测试 as /xyz.do?param=在线测试 with rule pattern ^/abc/(.*)$
访问日志
/xyz.do?param=????
编辑
进一步调试我发现这种行为只适用于查询字符串。我正在使用 Tomcat 8.0.35.
rewrite.config 文件
RewriteRule ^/abc/(.*)$ /xyz? [L]
RewriteRule ^/test/(.*)/(. *)$ /test/? [L]
我添加了一个自定义记录阀
public class CustomValve extends ValveBase {
private static final Logger logger = Logger.getLogger(CustomValve.class.getName());
public void invoke(Request request, Response response) throws IOException, ServletException {
HttpServletRequest httpServletRequest = request.getRequest();
String contextPath = request.getRequestURI();
logger.log(Level.SEVERE, "Context Path: "+contextPath);
String queryString = request.getQueryString();
if(queryString != null)
{
logger.log(Level.SEVERE, "QueryString: "+request.getQueryString());
}
else
{
logger.log(Level.INFO, "QueryString: Null");
}
getNext().invoke(request, response);
}
}
此记录阀配置有重写阀
context.xml
<Context>
<Valve className="org.apache.catalina.valves.rewrite.RewriteValve"/>
<Valve className="com.logging.valves.CustomValve"/>
</Context>
URL 访问过
http://localhost:8080/test/在线测试/在线测试
已记录自定义记录器
上下文路径:/test/%E5%9C%A8%E7%BA%BF%E6%B5%8B%E8%AF%95
QueryString: 在线测试
访问日志
/test/%E5%9C%A8%E7%BA%BF%E6%B5%8B%E8%AF%95????
请求 URI 中的非 ASCII 字符已编码,但查询字符串仍未编码。检查 Tomcat 的 RewriteValve 的实现,我发现请求 URI 已编码。
request.getCoyoteRequest().requestURI().setString(null);
CharChunk chunk = request.getCoyoteRequest().requestURI().getCharChunk();
chunk.recycle();
if (this.context) {
chunk.append(contextPath);
}
//encoding of request URI
chunk.append(URLEncoder.DEFAULT.encode(urlString));
request.getCoyoteRequest().requestURI().toChars();
但是查询字符串没有这样的编码
if (queryString != null) {
request.getCoyoteRequest().queryString().setString(null);
chunk = request.getCoyoteRequest().queryString().getCharChunk();
chunk.recycle();
chunk.append(queryString);
request.getCoyoteRequest().queryString().toChars();
}
有没有办法解决这个问题?
似乎是 RewriteValve 实现中的错误。