当 URL 路径中出现双斜杠时,如何使用 Elastic Beanstalk (Apache+Tomcat) 解决 HTTP 404 错误,例如https://uat.myserver//rest/s
Posted
技术标签:
【中文标题】当 URL 路径中出现双斜杠时,如何使用 Elastic Beanstalk (Apache+Tomcat) 解决 HTTP 404 错误,例如https://uat.myserver//rest/something【英文标题】:How to resolve HTTP 404 error with Elastic Beanstalk (Apache+Tomcat) when double-slash in URL path, e.g. https://uat.myserver//rest/something 【发布时间】:2021-06-04 16:02:22 【问题描述】:我有一个托管在 Amazon Web Services 中的 Java Web 应用程序,它运行在带有 Amazon Linux 的退役 Tomcat 8 上。
我尝试创建一个新环境来测试在最新的 Tomcat 8.5 上运行该应用程序,并在 Amazon Linux 2 上运行 Corretto 11。
在此过程中,我遇到了一个大问题,在我的应用程序中,它使用了一个基本 URL,例如https://myserver.com 它正在做一些字符串连接来添加路径,例如/rest/myendpoint 当然应该被解析为
https://myserver.com/rest/myendpoint
但不幸的是,它在不知不觉中通过 C# 的 new URL()
传递,它在连接之前附加了一个斜杠。
所以
https://myserver.com/rest/myendpoint
被发送到服务器
https://myserver.com/rest//myendpoint
(注意rest//
应该是rest/
)
在将 Java war 文件部署到新环境后,来自应用程序的一些请求失败并显示 404。我分析了这些网络日志,当然是所有在路径中有双转义的 URL。
作为在 Postman 中编写请求以使单斜杠正常工作的测试,双引号失败并出现 HTTP 404,就像应用程序一样。
现在的问题是应用已经在野外使用了,我们无法更改应用,因为这将涉及很长的延迟(构建它,应用商店批准过程,然后等待每个人升级应用) ,很可能是几个月。
我在 AWS 门户中找不到任何东西来配置它。
我确实尝试过切换到 nginx,但遇到了同样的错误。
我确实看到有人提到使用 .eb-extensions,但整个 apache re-write / mod 规则对我来说非常陌生。实际上,我想将 http:// 或 https:// 之后的任何双斜杠重写为单斜杠。你能告诉我如何做到这一点吗?
我正在将 Elastic Beanstalk 与 Tomcat(目前由 Apache 支持)和最新的 Tomcat 平台版本 - Tomcat 8.5 以及在 64 位 Amazon Linux 2 上运行的 Corretto 11 一起使用。
谢谢。
【问题讨论】:
生成 URL 的是 Java 还是 C#? 嗨@OlafKock 该应用程序是c#,但不幸的是,我等不及该应用程序被修复、推出和大多数用户更新。同时,服务器端需要在 AWS .ebexensions 中进行某种 Apache 重写来执行此清理任务。 ***.com/questions/17080652/… 应该给你必要的 RewriteRules,docs.aws.amazon.com/elasticbeanstalk/latest/dg/… 有放置文件的例子。 【参考方案1】:因为我真的不想与 .ebextensions 搞混,所以我扩展了一个现有的 servlet 过滤器(链中最早的)来检查路径。然后我就可以使用调度程序进行转发,并且效果很好。
虽然我确信我可以用 reg-ex 做一些更清洁的事情,但这对我来说已经成功了,我可以先用 Postman 在本地测试它。
package com.devology.servlet.filters;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
public class AuthenticationFilter implements Filter
public AuthenticationFilter()
private boolean doBeforeProcessing(ServletRequest request, ServletResponse response)
throws IOException, ServletException
HttpServletRequest hsr = (HttpServletRequest) request;
final String path = hsr.getServletPath();
String fullUrl = hsr.getRequestURL().toString();
String remoteAddress = hsr.getRemoteAddr();
// Example URL from bad app...
//
// http://localhost:8084/MyApp//rest/login
//
// path = /rest
// fullUrl = http://localhost:8084/MyApp//rest/login
// indexOfPath = ^ = 34
//
// If the character before the start of the path is also a slash then
// we need to internally forward
int indexOfPath = fullUrl.indexOf(path + "/");
boolean needsUrlRewrite = false;
if (indexOfPath != -1)
String previousCharacter = fullUrl.substring(indexOfPath - 1, indexOfPath);
needsUrlRewrite = "/".equals(previousCharacter);
if (needsUrlRewrite)
// Just take the path from the point of indexOfPath, .e.g /rest/login
String rewrittenPath = fullUrl.substring(indexOfPath);
RequestDispatcher dispatcher = request.getServletContext().getRequestDispatcher(rewrittenPath);
dispatcher.forward(request, response);
return false;
// Any other checks like authorisation, or return true to let all through
return true;
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
throws IOException, ServletException
if (doBeforeProcessing(request, response))
chain.doFilter(request, response);
@Override
public void init(FilterConfig fc) throws ServletException
// Your Init
@Override
public void destroy()
// Your cleanup
这假设您已经在 web.xml 中像这样配置它...
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
<filter>
<filter-name>AuthenticationFilter</filter-name>
<filter-class>com.devology.servlet.filters.AuthenticationFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AuthenticationFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.jsp</url-pattern>
<url-pattern>*.jspf</url-pattern>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>10</session-timeout>
</session-config>
<error-page>
<error-code>500</error-code>
<location>/error-500.html</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/error-404.html</location>
</error-page>
</web-app>
我没有解决 .ebextensions 和 Apache 配置的问题,因为我真的不知道自己在做什么,而上面的 servelet 过滤器正是我需要的。
【讨论】:
以上是关于当 URL 路径中出现双斜杠时,如何使用 Elastic Beanstalk (Apache+Tomcat) 解决 HTTP 404 错误,例如https://uat.myserver//rest/s的主要内容,如果未能解决你的问题,请参考以下文章
IDEA中用jetty启动web项目时,url路径包含双斜杠会返回404