Estou usando o S3 para hospedar um aplicativo javascript que usará pushStates HTML5. O problema é que, se o usuário marcar um dos URLs como favorito, ele não resolverá nada. O que eu preciso é a capacidade de receber todas as solicitações de URL e exibir o index.html raiz no meu bucket S3, em vez de apenas fazer um redirecionamento completo. Em seguida, meu aplicativo javascript poderia analisar o URL e exibir a página apropriada.
Existe alguma maneira de dizer ao S3 para servir o index.html para todas as solicitações de URL em vez de fazer redirecionamentos? Isso seria semelhante à configuração do apache para lidar com todas as solicitações recebidas, exibindo um único index.html, como neste exemplo: https://stackoverflow.com/a/10647521/1762614 . Eu realmente gostaria de evitar a execução de um servidor web apenas para lidar com essas rotas. Fazer tudo do S3 é muito atraente.
Respostas:
É muito fácil resolvê-lo sem invasões de URL, com a ajuda do CloudFront.
fonte
A maneira como consegui fazer isso funcionar é a seguinte:
Na seção Editar regras de redirecionamento do S3 Console para seu domínio, adicione as seguintes regras:
Isso redirecionará todos os caminhos que resultam em um 404 não encontrado no domínio raiz com uma versão hash-bang do caminho. Portanto, http://seudominio.com.br/posts será redirecionado para http://seudominio.com.br/#!/posts, desde que não haja arquivo em / posts.
Para usar HTML5 pushStates, no entanto, precisamos atender a essa solicitação e estabelecer manualmente o pushState adequado com base no caminho hash-bang. Então adicione isso na parte superior do seu arquivo index.html:
Isso pega o hash e o transforma em um pushState HTML5. A partir deste ponto, você pode usar os pushStates para ter caminhos não hash-bang no seu aplicativo.
fonte
<script language="javascript"> if (typeof(window.history.pushState) == 'function') { window.history.pushState(null, "Site Name", window.location.hash.substring(2)); } else { window.location.hash = window.location.hash.substring(2); } </script>
react-router
com que a solução usando HTML 5 pushStates e<ReplaceKeyPrefixWith>#/</ReplaceKeyPrefixWith>
Existem alguns problemas com a abordagem baseada em S3 / Redirect mencionada por outros.
A solução é:
Configure regras da página de erro para sua instância do Cloudfront. Nas regras de erro, especifique:
Código de resposta HTTP: 200
Configure uma instância do EC2 e configure um servidor nginx.
Posso ajudar em mais detalhes com relação à configuração do nginx, basta deixar uma nota. Aprendi da maneira mais difícil.
Depois que a distribuição da frente da nuvem for atualizada. Invalide seu cache do cloudfront uma vez para estar no modo intocado. Bata o URL no navegador e tudo deve ser bom.
fonte
If-Modified-Since
solicitação GET é enviada para a origem) - pode ser uma consideração útil para pessoas que não desejam configurar um servidor como na etapa 5.É tangencial, mas aqui está uma dica para quem usa a biblioteca React Router da Rackt com histórico de navegador (HTML5) que deseja hospedar no S3.
Suponha que um usuário visite
/foo/bear
seu site estático hospedado no S3. Dada a sugestão anterior de David , as regras de redirecionamento as enviarão para/#/foo/bear
. Se o seu aplicativo foi criado usando o histórico do navegador, isso não será muito bom. No entanto, seu aplicativo está carregado neste momento e agora pode manipular o histórico.Incluindo o histórico Rackt em nosso projeto (consulte também Utilizando históricos personalizados no projeto React Router), você pode adicionar um ouvinte que esteja ciente dos caminhos do histórico de hash e substituí-lo conforme apropriado, conforme ilustrado neste exemplo:
Para recapitular:
/foo/bear
para/#/foo/bear
.#/foo/bear
histórico detectará a notação do histórico.Link
Tag funcionarão conforme o esperado, assim como todas as outras funções do histórico do navegador. A única desvantagem que notei é o redirecionamento intersticial que ocorre na solicitação inicial.Isso foi inspirado por uma solução para o AngularJS e suspeito que possa ser facilmente adaptado a qualquer aplicativo.
fonte
browserHistory.listen
Eu vejo 4 soluções para este problema. Os três primeiros já foram abordados em respostas e o último é minha contribuição.
Defina o documento de erro como index.html.
Problema : o corpo da resposta estará correto, mas o código de status será 404, o que prejudica o SEO.
Defina as regras de redirecionamento.
Problema : o URL poluído
#!
e a página pisca quando carregada.Configure o CloudFront.
Problema : todas as páginas retornarão 404 da origem, portanto, você deve escolher se não armazenará nada em cache (TTL 0, conforme sugerido) ou se armazenará em cache e terá problemas ao atualizar o site.
Pré-renderize todas as páginas.
Problema : trabalho adicional para pré-renderizar páginas, especialmente quando as páginas são alteradas com frequência. Por exemplo, um site de notícias.
Minha sugestão é usar a opção 4. Se você pré-renderizar todas as páginas, não haverá erros 404 para as páginas esperadas. A página carregará bem e a estrutura assumirá o controle e agirá normalmente como um SPA. Você também pode definir o documento de erro para exibir uma página error.html genérica e uma regra de redirecionamento para redirecionar os erros 404 para uma página 404.html (sem o hashbang).
Em relação aos 403 erros proibidos, não os deixo acontecer. No meu aplicativo, considero que todos os arquivos no bucket do host são públicos e defino isso com a opção Todos com a permissão de leitura . Se o seu site tiver páginas privadas, permitir que o usuário veja o layout HTML não deve ser um problema. O que você precisa proteger são os dados e isso é feito no back-end.
Além disso, se você tiver ativos privados, como fotos de usuário, poderá salvá-los em outro depósito. Como os ativos privados precisam do mesmo cuidado que os dados e não podem ser comparados aos arquivos de ativos usados para hospedar o aplicativo.
fonte
Encontrei o mesmo problema hoje, mas a solução do @ Mark-Nutter estava incompleta para remover o hashbang do meu aplicativo angularjs.
Na verdade, você precisa ir para Editar permissões , clicar em Adicionar mais permissões e adicionar a lista correta no seu balde a todos. Com essa configuração, o AWS S3 agora poderá retornar o erro 404 e, em seguida, a regra de redirecionamento detectará o caso corretamente.
Bem assim :
E então você pode ir para Editar Regras de Redirecionamento e adicionar esta regra:
Aqui você pode substituir o nome do host subdomínio.domínio.fr pelo seu domínio e o KeyPrefix #! / Se você não usar o método hashbang para fins de SEO.
Obviamente, tudo isso funcionará apenas se você já tiver configurado o html5mode no seu aplicativo angular.
fonte
A solução mais fácil para fazer com que o aplicativo Angular 2+ veiculado no Amazon S3 e URLs diretos funcionem é especificar index.html como documentos de Índice e Erro na configuração do bucket do S3.
fonte
body
a resposta. O código de status será 404 e prejudicará o SEO.body
scripts que você importar,head
eles não funcionarão quando você atingir diretamente qualquer uma das sub-rotas no seu sitecomo o problema ainda está lá, eu acho que joguei outra solução. Meu caso foi que eu desejava implantar automaticamente todas as solicitações pull no s3 para teste antes de mesclar, tornando-as acessíveis em [mydomain] / pull-orders / [pr number] /
(por exemplo, www.example.com/pull-requests/822/ )
Que eu saiba, os cenários que não pertencem às regras s3 permitiriam ter vários projetos em um bucket usando o roteamento html5; portanto, embora a sugestão mais votada funcione para um projeto na pasta raiz, não para vários projetos em suas próprias subpastas.
Então apontei meu domínio para o meu servidor, onde a seguinte configuração do nginx fez o trabalho
ele tenta obter o arquivo e, se não for encontrado, assume que é a rota html5 e tenta isso. Se você possui uma página angular 404 para rotas não encontradas, nunca acessará @not_found e retornará a página 404 angular em vez de arquivos não encontrados, que podem ser corrigidos com alguma regra if em @get_routes ou algo assim.
Eu tenho que dizer que não me sinto muito à vontade na área de configuração do nginx e usando o regex, eu trabalhei com algumas tentativas e erros, portanto, enquanto isso funciona, tenho certeza de que há espaço para melhorias e, por favor, compartilhe seus pensamentos .
Nota : remova as regras de redirecionamento s3 se você as tiver na configuração do S3.
e btw funciona no Safari
fonte
Estava procurando o mesmo tipo de problema. Acabei usando uma mistura das soluções sugeridas descritas acima.
Primeiro, eu tenho um bucket s3 com várias pastas, cada pasta representa um site react / redux. Eu também uso o cloudfront para invalidação de cache.
Então, eu tive que usar as regras de roteamento para dar suporte ao 404 e redirecioná-las para uma configuração de hash:
No meu código js, eu precisava lidar com isso com uma
baseName
configuração para o react-router. Antes de tudo, verifique se suas dependências são interoperáveis, eu instalei com ashistory==4.0.0
quais era incompatívelreact-router==3.0.1
.Minhas dependências são:
Criei um
history.js
arquivo para carregar o histórico:Esse trecho de código permite manipular o 404 enviado pelo servidor com um hash e substituí-lo no histórico para carregar nossas rotas.
Agora você pode usar esse arquivo para configurar sua loja e seu arquivo raiz.
Espero que ajude. Você notará que, com essa configuração, eu uso o injetor redux e um injetor homebrew sagas para carregar o javascript de forma assíncrona, via roteamento. Não se importe com essas linhas.
fonte
Agora você pode fazer isso com o Lambda @ Edge para reescrever os caminhos
Aqui está uma função lambda @ Edge em funcionamento:
Nos seus comportamentos na nuvem, você os editará para adicionar uma chamada à função lambda em "Solicitação do visualizador"
Tutorial completo: https://aws.amazon.com/blogs/compute/implementing-default-directory-indexes-in-amazon-s3-backed-amazon-cloudfront-origins-using-lambdaedge/
fonte
return callback(null, request);
Se você chegou aqui procurando uma solução que funcione com o React Router e o AWS Amplify Console - você já sabe que não pode usar as regras de redirecionamento do CloudFront diretamente, pois o Amplify Console não expõe o CloudFront Distribution para o aplicativo.
A solução, no entanto, é muito simples - você só precisa adicionar uma regra de redirecionamento / reescrita no Amplify Console como esta:
Consulte os links a seguir para obter mais informações (e regra de cópia amigável na captura de tela):
fonte
Eu mesmo estava procurando uma resposta para isso. O S3 parece suportar apenas redirecionamentos, você não pode simplesmente reescrever o URL e retornar silenciosamente um recurso diferente. Estou pensando em usar meu script de construção para simplesmente fazer cópias do meu index.html em todos os locais de caminho necessários. Talvez isso funcione para você também.
fonte
Apenas para colocar a resposta extremamente simples. Basta usar a estratégia de localização de hash para o roteador se você estiver hospedando no S3.
exportar constante AppRoutingModule: ModuleWithProviders = RouterModule.forRoot (rotas, {useHash: true, scrollPositionRestoration: 'enabled'});
fonte