GlassFish 7.0.21+JDK17:含非ASCII字符URL在HTTP/2返回404,HTTP/1.1正常
GlassFish 7 HTTP/2 下含非ASCII字符URL返回404的问题排查与解决
问题确认
这个问题确实有不少开发者反馈过,属于GlassFish 7在HTTP/2协议下处理UTF-8编码URL的兼容性问题。
是否为GlassFish Bug?
是的,这是GlassFish 7.x版本中HTTP/2处理模块的已知Bug。核心原因是HTTP/1.1和HTTP/2对URL解码的逻辑不一致:HTTP/1.1会正确解析UTF-8编码的非ASCII字符路径,但HTTP/2模块在解码时未正确应用UTF-8规则,导致实际解析的路径和应用中定义的路由不匹配,最终返回404。
可行的Workaround与配置方案
1. 临时降级HTTP/2(快速生效)
在GlassFish的域配置文件domain.xml中,找到对应HTTPS的network-listener节点(默认名为http-listener-2),添加或修改http2-enabled属性为false,强制使用HTTP/1.1处理HTTPS请求:
<network-listener name="http-listener-2" protocol="http-listener-2" port="8181" thread-pool="http-thread-pool" transport="tcp" http2-enabled="false"></network-listener>
修改后重启GlassFish即可生效。
2. 调整URL解码配置(针对HTTP/2)
在domain.xml中为HTTP/2协议添加UTF-8解码配置:
找到protocol节点中对应HTTP/2的配置(通常是http2-protocol),添加default-encoding属性:
<protocol name="http2-protocol"> <http2 default-encoding="UTF-8"></http2> </protocol>
同时确保全局http节点的编码配置一致:
<http default-encoding="UTF-8"></http>
修改后重启服务测试。
3. 应用层适配(代码层面兼容)
如果无法修改服务器配置,可以在应用中添加Servlet过滤器手动处理HTTP/2请求的路径解码:
@WebFilter("/*") public class PathDecodeFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; String path = req.getRequestURI(); // 针对HTTP/2请求手动解码UTF-8路径 if ("h2".equals(req.getProtocol())) { path = URLDecoder.decode(path, StandardCharsets.UTF_8); HttpServletRequest wrappedReq = new HttpServletRequestWrapper(req) { @Override public String getRequestURI() { return path; } }; chain.doFilter(wrappedReq, response); } else { chain.doFilter(request, response); } } }
注意:需确保应用路由定义的是原始UTF-8路径,避免重复解码导致异常。
是否需要修改应用设置?
如果采用服务器配置调整的方案,无需修改应用代码;如果选择应用层适配,则需要添加上述过滤器。另外,建议在web.xml中统一设置字符编码:
<filter> <filter-name>encodingFilter</filter-name> <filter-class>org.apache.catalina.filters.SetCharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
内容的提问来源于stack exchange,提问作者andy
相关产品推荐
相关产品推荐

