我使用S3托管一个javascript应用程序,将使用HTML5 pushStates。问题是,如果用户书签了任何url,它将不会解析为任何东西。我需要的是能够接受所有url请求,并在我的S3桶中提供根index.html,而不仅仅是进行完全重定向。然后我的javascript应用程序可以解析URL并提供适当的页面。

有没有办法告诉S3为所有URL请求服务index.html,而不是做重定向?这类似于通过提供一个index.html来设置apache来处理所有传入的请求,如本例中的https://stackoverflow.com/a/10647521/1762614。我真的希望避免仅仅为了处理这些路由而运行web服务器。从S3执行所有操作非常有吸引力。


当前回答

大多数建议的解决方案(尤其是最流行的答案)的问题是,对于不存在的后端资源,您永远不会看到404错误。如果希望继续得到404,请参考此解决方案

I added a root path to all my routes (that's new to this solution) e.g. all my route-paths start with the same front end root... in place of paths /foo/baz, /foo2/baz I now have /root/foo/baz , /root/foo2/baz paths. The choice of the front-end root is such that it does not conflict with any real folder or path at the back-end. Now I can use this root to create simple redirection rules anywhere, I like. All my redirection changes will be impacting only this path and everything else will be as earlier.

这是我在s3桶中添加的重定向规则

[
    {
        "Condition": {
            "HttpErrorCodeReturnedEquals": "404",
            "KeyPrefixEquals": "root/"
        },
        "Redirect": {
            "HostName": "mydomain.com",
            "ReplaceKeyPrefixWith": "#/"
        }
    }
]

甚至是跟随

[
        {
            "Condition": {
               
                "KeyPrefixEquals": "root/"
            },
            "Redirect": {
                "HostName": "mydomain.com",
                "ReplaceKeyPrefixWith": "#/"
            }
        }
    ]

在此之后,/root/foo/baz被重定向到/#/foo/baz,页面在主页加载,没有错误。

我在装载Vue应用程序后添加了以下代码。它将把我的应用程序带到所需的路线。您可以更换路由器。push部分根据Angular或你正在使用的任何东西。

if(location.href.includes("#"))
{
  let currentRoute = location.href.split("#")[1];

  router.push({ path: `/root${currentRoute}` })
}

即使您没有在s3级别使用重定向,在您可能喜欢的任何其他重定向中,为所有路由提供一个单一的基础也会很方便。它帮助后端识别这不是一个真正的后端资源的请求,前端应用程序将能够处理它。

其他回答

我做到这一点的方法如下:

在域的S3控制台的“编辑重定向规则”部分中,添加以下规则:

<RoutingRules>
  <RoutingRule>
    <Condition>
      <HttpErrorCodeReturnedEquals>404</HttpErrorCodeReturnedEquals>
    </Condition>
    <Redirect>
      <HostName>yourdomainname.com</HostName>
      <ReplaceKeyPrefixWith>#!/</ReplaceKeyPrefixWith>
    </Redirect>
  </RoutingRule>
</RoutingRules>

这将导致404错误的所有路径重定向到根域,并显示路径的散列版本。所以http://yourdomainname.com/posts将重定向到http://yourdomainname.com/#!如果/posts上没有文件。

然而,要使用HTML5的pushState,我们需要接受这个请求,并根据散列路径手动建立正确的pushState。所以把这个添加到index.html文件的顶部:

<script>
  history.pushState({}, "entry page", location.hash.substring(1));
</script>

这将获取散列并将其转换为HTML5 pushState。从这一点开始,你可以使用pushStates在你的应用程序中拥有非哈希键路径。

我自己也在寻找答案。S3似乎只支持重定向,你不能只是重写URL并无声地返回一个不同的资源。我正在考虑使用我的构建脚本在所有需要的路径位置简单地复制index.html。也许这对你也有用。

在2022年,Lambda函数是

函数处理程序(事件){ Var request = event.request; Var uri = request.uri; if (uri.endsWith("/")) { 请求。Uri += "index.html" } else if (!uri.includes(".")){ 请求。Uri += "/index.html" } 返回请求; }

大多数建议的解决方案(尤其是最流行的答案)的问题是,对于不存在的后端资源,您永远不会看到404错误。如果希望继续得到404,请参考此解决方案

I added a root path to all my routes (that's new to this solution) e.g. all my route-paths start with the same front end root... in place of paths /foo/baz, /foo2/baz I now have /root/foo/baz , /root/foo2/baz paths. The choice of the front-end root is such that it does not conflict with any real folder or path at the back-end. Now I can use this root to create simple redirection rules anywhere, I like. All my redirection changes will be impacting only this path and everything else will be as earlier.

这是我在s3桶中添加的重定向规则

[
    {
        "Condition": {
            "HttpErrorCodeReturnedEquals": "404",
            "KeyPrefixEquals": "root/"
        },
        "Redirect": {
            "HostName": "mydomain.com",
            "ReplaceKeyPrefixWith": "#/"
        }
    }
]

甚至是跟随

[
        {
            "Condition": {
               
                "KeyPrefixEquals": "root/"
            },
            "Redirect": {
                "HostName": "mydomain.com",
                "ReplaceKeyPrefixWith": "#/"
            }
        }
    ]

在此之后,/root/foo/baz被重定向到/#/foo/baz,页面在主页加载,没有错误。

我在装载Vue应用程序后添加了以下代码。它将把我的应用程序带到所需的路线。您可以更换路由器。push部分根据Angular或你正在使用的任何东西。

if(location.href.includes("#"))
{
  let currentRoute = location.href.split("#")[1];

  router.push({ path: `/root${currentRoute}` })
}

即使您没有在s3级别使用重定向,在您可能喜欢的任何其他重定向中,为所有路由提供一个单一的基础也会很方便。它帮助后端识别这不是一个真正的后端资源的请求,前端应用程序将能够处理它。

在CloudFront的帮助下,不需要url黑客就可以很容易地解决这个问题。

创建S3桶,例如:react 使用以下设置创建CloudFront发行版: 默认根对象:index.html 来源域名:S3桶域名,例如:react.s3.amazonaws.com 转到错误页面选项卡,单击创建自定义错误响应: HTTP错误码:403:禁止(404:未找到,在S3静态网站的情况下) 自定义错误响应:是 响应页面路径:/index.html HTTP响应码:200:OK 点击创建