我使用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执行所有操作非常有吸引力。


当前回答

既然问题仍然存在,我想我提出另一个解决方案。 我的情况是,我想在合并之前自动将所有拉请求部署到s3进行测试,使它们可以在[mydomain]/pull-requests/[pr number]/上访问 (例如www.example.com/pull-requests/822/)

据我所知,没有s3规则的场景允许在一个桶中使用html5路由有多个项目,所以上面大多数投票建议适用于根文件夹中的项目,不适用于自己子文件夹中的多个项目。

所以我把我的域指向我的服务器,在那里遵循nginx配置做的工作

location /pull-requests/ {
    try_files $uri @get_files;
}
location @get_files {
    rewrite ^\/pull-requests\/(.*) /$1 break;
    proxy_pass http://<your-amazon-bucket-url>;
    proxy_intercept_errors on;
    recursive_error_pages on;
    error_page 404 = @get_routes;
}

location @get_routes {
    rewrite ^\/(\w+)\/(.+) /$1/ break;
    proxy_pass http://<your-amazon-bucket-url>;
    proxy_intercept_errors on;
    recursive_error_pages on;
    error_page 404 = @not_found;
}

location @not_found {
    return 404;
}

它尝试获取文件,如果没有找到,则假设它是html5路由并尝试。如果你在angular的404页面中没有找到路由,你将永远不会到达@not_found,而会返回angular 404页面而不是not found files,这可以通过在@get_routes中添加If规则来修复。

我不得不说我在nginx配置和使用regex方面感到不太舒服,我得到了这个工作,经过了一些试验和错误,所以虽然这是有效的,但我相信有改进的空间,请分享你的想法。

注意:如果在s3配置中有重定向规则,请删除它们。

顺便说一下,在Safari中工作

其他回答

我今天遇到了同样的问题,但是@Mark-Nutter的解决方案不完整,无法从我的angularjs应用程序中删除hashbang。

事实上,你必须去编辑权限,点击添加更多权限,然后在你的桶中添加正确的列表给每个人。通过此配置,AWS S3现在将能够返回404错误,然后重定向规则将正确地捕获这种情况。

就像这样:

然后你可以去编辑重定向规则并添加这个规则:

<RoutingRules>
    <RoutingRule>
        <Condition>
            <HttpErrorCodeReturnedEquals>404</HttpErrorCodeReturnedEquals>
        </Condition>
        <Redirect>
            <HostName>subdomain.domain.fr</HostName>
            <ReplaceKeyPrefixWith>#!/</ReplaceKeyPrefixWith>
        </Redirect>
    </RoutingRule>
</RoutingRules>

在这里,您可以将HostName subdomain.domain.fr替换为您的域和KeyPrefix #!/如果你不使用hashbang方法用于SEO目的。

当然,只有在你的angular应用中已经设置了html5mode,所有这些才会起作用。

$locationProvider.html5Mode(true).hashPrefix('!');

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

既然问题仍然存在,我想我提出另一个解决方案。 我的情况是,我想在合并之前自动将所有拉请求部署到s3进行测试,使它们可以在[mydomain]/pull-requests/[pr number]/上访问 (例如www.example.com/pull-requests/822/)

据我所知,没有s3规则的场景允许在一个桶中使用html5路由有多个项目,所以上面大多数投票建议适用于根文件夹中的项目,不适用于自己子文件夹中的多个项目。

所以我把我的域指向我的服务器,在那里遵循nginx配置做的工作

location /pull-requests/ {
    try_files $uri @get_files;
}
location @get_files {
    rewrite ^\/pull-requests\/(.*) /$1 break;
    proxy_pass http://<your-amazon-bucket-url>;
    proxy_intercept_errors on;
    recursive_error_pages on;
    error_page 404 = @get_routes;
}

location @get_routes {
    rewrite ^\/(\w+)\/(.+) /$1/ break;
    proxy_pass http://<your-amazon-bucket-url>;
    proxy_intercept_errors on;
    recursive_error_pages on;
    error_page 404 = @not_found;
}

location @not_found {
    return 404;
}

它尝试获取文件,如果没有找到,则假设它是html5路由并尝试。如果你在angular的404页面中没有找到路由,你将永远不会到达@not_found,而会返回angular 404页面而不是not found files,这可以通过在@get_routes中添加If规则来修复。

我不得不说我在nginx配置和使用regex方面感到不太舒服,我得到了这个工作,经过了一些试验和错误,所以虽然这是有效的,但我相信有改进的空间,请分享你的想法。

注意:如果在s3配置中有重定向规则,请删除它们。

顺便说一下,在Safari中工作

这里没有提到的解决方案是使用CloudFront函数在查看器请求时将请求URI重写为index.html:

function handler(event) {
    var request = event.request;
    request.uri = '/index.html';
    return request;
}

在2022年,Lambda函数是

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