Mar*_*ter 225 redirect routing amazon-s3 amazon-web-services pushstate
我使用S3来托管一个将使用HTML5 pushStates的javascript应用程序.问题是如果用户为任何URL添加书签,它将无法解析为任何内容.我需要的是能够获取所有URL请求并在我的S3存储桶中提供root index.html,而不仅仅是执行完全重定向.然后我的javascript应用程序可以解析URL并提供正确的页面.
有没有办法告诉S3为所有URL请求提供index.html而不是重定向?这与设置apache以通过提供单个index.html来处理所有传入请求类似,如下例所示:https://stackoverflow.com/a/10647521/1762614.我真的想避免运行Web服务器来处理这些路由.从S3做一切非常有吸引力.
len*_*ten 250
使用CloudFront帮助,在没有网址攻击的情况下解决它非常容易.
Mar*_*ter 195
我能够让它工作的方式如下:
在您的域的S3控制台的" 编辑重定向规则"部分中,添加以下规则:
<RoutingRules>
<RoutingRule>
<Condition>
<HttpErrorCodeReturnedEquals>404</HttpErrorCodeReturnedEquals>
</Condition>
<Redirect>
<HostName>yourdomainname.com</HostName>
<ReplaceKeyPrefixWith>#!/</ReplaceKeyPrefixWith>
</Redirect>
</RoutingRule>
</RoutingRules>
Run Code Online (Sandbox Code Playgroud)
这将使用路径的hash-bang版本将导致未找到404的所有路径重定向到根域.因此http://yourdomainname.com/posts将重定向到http://yourdomainname.com/#!/posts,前提是/ post没有文件.
但是,要使用HTML5 pushStates,我们需要接受此请求并根据hash-bang路径手动建立正确的pushState.所以将它添加到index.html文件的顶部:
<script>
history.pushState({}, "entry page", location.hash.substring(1));
</script>
Run Code Online (Sandbox Code Playgroud)
这会抓取哈希并将其转换为HTML5 pushState.从这一点开始,您可以使用pushStates在应用程序中使用非哈希爆炸路径.
moh*_*297 125
其他人提到的基于S3/Redirect的方法几乎没有问题.
解决方案是:
5.对于SEO需求+确保您的index.html不缓存,请执行以下操作:
关于nginx设置,我可以提供更多详细信息,只需留言即可.已经很难学会了.
一旦云前端分发更新.使您的云端缓存无效一次,使其处于原始模式.点击浏览器中的网址,一切都应该是好的.
Mic*_*ers 17
它是切向的,但是对于那些使用具有(HTML5)浏览器历史记录而想要在S3上托管的Rackt的 React Router库的人来说,这是一个提示.
假设用户访问/foo/bearS3托管的静态网站.鉴于大卫 先前的建议,重定向规则将发送给他们/#/foo/bear.如果您的应用程序是使用浏览器历史记录构建的,那么这将无济于事.但是,此时您的应用程序已加载,现在可以操作历史记录.
在我们的项目中包括Rackt 历史记录(另请参阅使用 React Router项目中的Custom Histories),您可以添加一个知道哈希历史路径的侦听器并根据需要替换路径,如下例所示:
import ReactDOM from 'react-dom';
/* Application-specific details. */
const route = {};
import { Router, useRouterHistory } from 'react-router';
import { createHistory } from 'history';
const history = useRouterHistory(createHistory)();
history.listen(function (location) {
const path = (/#(\/.*)$/.exec(location.hash) || [])[1];
if (path) history.replace(path);
});
ReactDOM.render(
<Router history={history} routes={route}/>,
document.body.appendChild(document.createElement('div'))
);
Run Code Online (Sandbox Code Playgroud)
回顾一下:
/foo/bear指向/#/foo/bear.#/foo/bear历史记录.Link标签将按预期工作,所有其他浏览器历史记录功能也将如此.我注意到的唯一缺点是初始请求时发生的插页式重定向.
这是受AngularJS解决方案的启发,我怀疑可以很容易地适应任何应用程序.
Zan*_*non 13
我看到了这个问题的4个解决方案.前三个已经包含在答案中,最后一个是我的贡献.
将错误文档设置为index.html.
问题:响应正文是正确的,但状态代码将是404,这会伤害搜索引擎优化.
设置重定向规则.
问题:#!加载后,URL被污染,页面闪烁.
配置CloudFront.
问题:所有页面都将从原点返回404,因此您需要选择是否不缓存任何内容(建议使用TTL 0),或者在更新站点时缓存并出现问题.
预呈现所有页面.
问题:预渲染页面的额外工作,特别是当页面频繁更改时.例如,一个新闻网站.
我的建议是使用选项4.如果您预渲染所有页面,预期页面将不会有404错误.页面将加载正常,框架将采取控制并正常作为SPA.您还可以设置错误文档以显示通用error.html页面和重定向规则,以将404错误重定向到404.html页面(没有hashbang).
关于403 Forbidden错误,我根本不让它们发生.在我的应用程序中,我认为主机存储桶中的所有文件都是公共的,我使用具有读取权限的everyone选项设置它.如果您的网站具有私有页面,则让用户看到HTML 布局应该不是问题.您需要保护的是数据,这在后端完成.
此外,如果您有私有资产,例如用户照片,则可以将它们保存在另一个存储桶中.由于私有资产需要与数据相同的谨慎,因此无法与用于托管应用程序的资产文件进行比较.
dav*_*era 12
我今天遇到了同样的问题,但@ 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>
Run Code Online (Sandbox Code Playgroud)
在这里,您可以使用您的域和KeyPrefix#!/ 替换HostName subdomain.domain.fr,如果您不使用hashbang方法进行SEO目的.
当然,只有在角度应用程序中已经安装了html5mode时,所有这些才有效.
$locationProvider.html5Mode(true).hashPrefix('!');
Run Code Online (Sandbox Code Playgroud)
cla*_*mes 12
与使用 的另一个答案类似Lambda@Edge,您可以使用Cloudfront Functions (这是免费层的一部分)。
我的网址结构是这样的:
example.com- 在 S3 上托管的 React SPAexample.com/blog- 博客托管在 EC2 上由于我将博客托管在与 SPA 相同的域上,因此我无法使用使用默认错误页面的 CloudFront 403/404 错误页面的建议答案。
我的 CloudFront 设置是:
/blogdefault (*)default (*)将 CloudFront 功能设置为行为的“查看者请求”我正在使用基于AWS 示例的CloudFront 函数。这可能不适用于所有情况,但我的 React 应用程序的 URL 结构不包含任何..
function handler(event) {
var request = event.request;
var uri = request.uri;
// If the request is not for an asset (js, png, etc), render the index.html
if (!uri.includes('.')) {
request.uri = '/index.html';
}
return request;
}
Run Code Online (Sandbox Code Playgroud)
我已将我的功能更新为:
function handler(event) {
var request = event.request;
var uri = request.uri;
// Check whether the URI is missing a file name.
if (uri.endsWith('/')) {
request.uri += 'index.html';
}
// Check whether the URI is missing a file extension.
else if (!uri.includes('.')) {
request.uri += '/index.html';
}
return request;
}
Run Code Online (Sandbox Code Playgroud)
Ser*_*rov 10
从Amazon S3提供Angular 2+应用程序和直接URL工作的最简单的解决方案是将index.html指定为S3存储桶配置中的索引和错误文档.
Lor*_*ren 10
您现在可以使用 Lambda@Edge 来重写路径
这是一个有效的 lambda@Edge 函数:
'use strict';
exports.handler = (event, context, callback) => {
// Extract the request from the CloudFront event that is sent to Lambda@Edge
var request = event.Records[0].cf.request;
// Extract the URI from the request
var olduri = request.uri;
// Match any '/' that occurs at the end of a URI. Replace it with a default index
var newuri = olduri.replace(/\/$/, '\/index.html');
// Log the URI as received by CloudFront and the new URI to be used to fetch from origin
console.log("Old URI: " + olduri);
console.log("New URI: " + newuri);
// Replace the received URI with the URI that includes the index page
request.uri = newuri;
return callback(null, request);
};
Run Code Online (Sandbox Code Playgroud)
在您的云端行为中,您将编辑它们以在“查看器请求”上添加对该 lambda 函数的调用

完整教程:https : //aws.amazon.com/blogs/compute/implementing-default-directory-indexes-in-amazon-s3-backed-amazon-cloudfront-origins-using-lambdaedge/
小智 7
转到存储桶的静态网站托管设置并将错误文档设置为index.html。
小智 5
由于问题仍然存在,我虽然提出了另一个解决方案。我的情况是,我想在合并之前将所有拉取请求自动部署到 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;
}
Run Code Online (Sandbox Code Playgroud)
它尝试获取该文件,如果找不到,则假定它是 HTML5 路由并尝试该文件。如果您有一个未找到路线的 404 角度页面,您将永远不会到达 @not_found 并返回角度 404 页面而不是未找到文件,这可以通过一些 if 规则@get_routes或其他内容来修复。
我不得不说我在 Nginx 配置和使用正则表达式方面感觉不太舒服,我通过一些尝试和错误得到了这个工作,所以虽然这有效,但我确信还有改进的空间,请分享你的想法。
注意:如果 S3 配置中有 s3 重定向规则,请删除它们。
顺便说一句,在 Safari 中工作
正在寻找同样的问题。我最终混合使用了上述建议的解决方案。
首先,我有一个包含多个文件夹的 s3 存储桶,每个文件夹代表一个 react/redux 网站。我还使用 cloudfront 进行缓存失效。
所以我不得不使用路由规则来支持 404 并将它们重定向到一个哈希配置:
<RoutingRules>
<RoutingRule>
<Condition>
<KeyPrefixEquals>website1/</KeyPrefixEquals>
<HttpErrorCodeReturnedEquals>404</HttpErrorCodeReturnedEquals>
</Condition>
<Redirect>
<Protocol>https</Protocol>
<HostName>my.host.com</HostName>
<ReplaceKeyPrefixWith>website1#</ReplaceKeyPrefixWith>
</Redirect>
</RoutingRule>
<RoutingRule>
<Condition>
<KeyPrefixEquals>website2/</KeyPrefixEquals>
<HttpErrorCodeReturnedEquals>404</HttpErrorCodeReturnedEquals>
</Condition>
<Redirect>
<Protocol>https</Protocol>
<HostName>my.host.com</HostName>
<ReplaceKeyPrefixWith>website2#</ReplaceKeyPrefixWith>
</Redirect>
</RoutingRule>
<RoutingRule>
<Condition>
<KeyPrefixEquals>website3/</KeyPrefixEquals>
<HttpErrorCodeReturnedEquals>404</HttpErrorCodeReturnedEquals>
</Condition>
<Redirect>
<Protocol>https</Protocol>
<HostName>my.host.com</HostName>
<ReplaceKeyPrefixWith>website3#</ReplaceKeyPrefixWith>
</Redirect>
</RoutingRule>
</RoutingRules>
Run Code Online (Sandbox Code Playgroud)
在我的 js 代码中,我需要使用baseNamereact-router的配置来处理它。首先,确保您的依赖项是可互操作的,我安装了history==4.0.0与react-router==3.0.1.
我的依赖项是:
我创建了一个history.js用于加载历史记录的文件:
import {useRouterHistory} from 'react-router';
import createBrowserHistory from 'history/lib/createBrowserHistory';
export const browserHistory = useRouterHistory(createBrowserHistory)({
basename: '/website1/',
});
browserHistory.listen((location) => {
const path = (/#(.*)$/.exec(location.hash) || [])[1];
if (path) {
browserHistory.replace(path);
}
});
export default browserHistory;
Run Code Online (Sandbox Code Playgroud)
这段代码允许使用散列处理服务器发送的 404,并在历史记录中替换它们以加载我们的路由。
您现在可以使用此文件来配置您的商店和根文件。
import {routerMiddleware} from 'react-router-redux';
import {applyMiddleware, compose} from 'redux';
import rootSaga from '../sagas';
import rootReducer from '../reducers';
import {createInjectSagasStore, sagaMiddleware} from './redux-sagas-injector';
import {browserHistory} from '../history';
export default function configureStore(initialState) {
const enhancers = [
applyMiddleware(
sagaMiddleware,
routerMiddleware(browserHistory),
)];
return createInjectSagasStore(rootReducer, rootSaga, initialState, compose(...enhancers));
}
Run Code Online (Sandbox Code Playgroud)
import React, {PropTypes} from 'react';
import {Provider} from 'react-redux';
import {Router} from 'react-router';
import {syncHistoryWithStore} from 'react-router-redux';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import variables from '!!sass-variable-loader!../../../css/variables/variables.prod.scss';
import routesFactory from '../routes';
import {browserHistory} from '../history';
const muiTheme = getMuiTheme({
palette: {
primary1Color: variables.baseColor,
},
});
const Root = ({store}) => {
const history = syncHistoryWithStore(browserHistory, store);
const routes = routesFactory(store);
return (
<Provider {...{store}}>
<MuiThemeProvider muiTheme={muiTheme}>
<Router {...{history, routes}} />
</MuiThemeProvider>
</Provider>
);
};
Root.propTypes = {
store: PropTypes.shape({}).isRequired,
};
export default Root;
Run Code Online (Sandbox Code Playgroud)
希望能帮助到你。你会注意到这个配置我使用 redux 注入器和自制的 sagas 注入器通过路由异步加载 javascript。不要介意这些行。
我自己也在寻找这个问题的答案。S3 似乎只支持重定向,您不能只是重写 URL 并默默地返回不同的资源。我正在考虑使用我的构建脚本来简单地在所有必需的路径位置中复制我的index.html。也许这对你也有用。
| 归档时间: |
|
| 查看次数: |
76535 次 |
| 最近记录: |