J'utilise S3 pour héberger une application javascript qui utilisera les pushStates HTML5. Le problème est que si l'utilisateur met en signet l'une des URL, il ne résoudra rien. Ce dont j'ai besoin, c'est de pouvoir prendre toutes les demandes d'URL et servir le root index.html dans mon compartiment S3, plutôt que de simplement faire une redirection complète. Ensuite, mon application javascript pourrait analyser l'URL et diffuser la page appropriée.
Existe-t-il un moyen de dire à S3 de servir le fichier index.html pour toutes les demandes d'URL au lieu de faire des redirections? Cela serait similaire à la configuration d'apache pour gérer toutes les demandes entrantes en servant un seul index.html comme dans cet exemple: https://stackoverflow.com/a/10647521/1762614 . Je voudrais vraiment éviter d'exécuter un serveur Web juste pour gérer ces routes. Tout faire depuis S3 est très attrayant.
Réponses:
Il est très facile de le résoudre sans piratage d'URL, avec l'aide de CloudFront.
la source
La façon dont j'ai pu faire fonctionner cela est la suivante:
Dans la section Modifier les règles de redirection de la console S3 pour votre domaine, ajoutez les règles suivantes:
Cela redirigera tous les chemins qui se traduisent par un 404 introuvable sur votre domaine racine avec une version hachée du chemin. Alors http://yourdomainname.com/posts redirigera à http://yourdomainname.com/#!/posts fourni il n'y a pas de fichier à / messages.
Cependant, pour utiliser les pushStates HTML5, nous devons prendre cette demande et établir manuellement le pushState approprié en fonction du chemin de hachage. Ajoutez donc ceci en haut de votre fichier index.html:
Cela saisit le hachage et le transforme en un pushState HTML5. À partir de ce moment, vous pouvez utiliser pushStates pour avoir des chemins non-hash-bang dans votre application.
la source
<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
cette solution en utilisant les pushStates HTML5 et<ReplaceKeyPrefixWith>#/</ReplaceKeyPrefixWith>
Il y a peu de problèmes avec l'approche basée sur S3 / Redirect mentionnée par d'autres.
La solution est:
Configurez les règles de page d'erreur pour votre instance Cloudfront. Dans les règles d'erreur, spécifiez:
Code de réponse HTTP: 200
Configurez une instance EC2 et configurez un serveur nginx.
Je peux vous aider dans plus de détails en ce qui concerne la configuration de nginx, laissez simplement une note. Je l'ai appris à la dure.
Une fois la mise à jour de la distribution cloud front. Invalidez une fois votre cache cloudfront pour être en mode vierge. Appuyez sur l'URL dans le navigateur et tout devrait être bon.
la source
If-Modified-Since
demande GET est envoyée à l'origine) - peut être une considération utile pour les personnes qui ne veulent pas configurer un serveur comme à l'étape 5.C'est tangentiel, mais voici un conseil pour ceux qui utilisent la bibliothèque React Router de Rackt avec l' historique du navigateur (HTML5) qui souhaitent héberger sur S3.
Supposons qu'un utilisateur visite
/foo/bear
votre site Web statique hébergé par S3. Compte tenu de la suggestion précédente de David , les règles de redirection les enverront à/#/foo/bear
. Si votre application est construite à l'aide de l'historique du navigateur, cela ne fera pas grand chose. Cependant, votre application est chargée à ce stade et elle peut désormais manipuler l'historique.En incluant l' historique Rackt dans notre projet (voir également Utilisation d'histoires personnalisées du projet React Router), vous pouvez ajouter un écouteur qui connaît les chemins de l'historique de hachage et remplacer le chemin si nécessaire, comme illustré dans cet exemple:
Récapituler:
/foo/bear
vers/#/foo/bear
.#/foo/bear
notation d'historique.Link
les balises fonctionneront comme prévu, comme toutes les autres fonctions d'historique du navigateur. Le seul inconvénient que j'ai remarqué est la redirection interstitielle qui se produit à la demande initiale.Cela a été inspiré par une solution pour AngularJS , et je soupçonne qu'il pourrait être facilement adapté à n'importe quelle application.
la source
browserHistory.listen
Je vois 4 solutions à ce problème. Les 3 premiers étaient déjà couverts dans les réponses et le dernier est ma contribution.
Définissez le document d'erreur sur index.html.
Problème : le corps de la réponse sera correct, mais le code d'état sera 404, ce qui nuit au référencement.
Définissez les règles de redirection.
Problème : l'URL polluée par
#!
et la page clignote lors du chargement.Configurez CloudFront.
Problème : toutes les pages renverront 404 d'origine, vous devez donc choisir si vous ne mettrez rien en cache (TTL 0 comme suggéré) ou si vous mettrez en cache et rencontrez des problèmes lors de la mise à jour du site.
Prérender toutes les pages.
Problème : travail supplémentaire pour les pages de pré-rendu, spécialement lorsque les pages changent fréquemment. Par exemple, un site Web d'actualités.
Ma suggestion est d'utiliser l'option 4. Si vous pré-rendez toutes les pages, il n'y aura pas d'erreurs 404 pour les pages attendues. La page se chargera correctement et le framework prendra le contrôle et agira normalement comme un SPA. Vous pouvez également définir le document d'erreur pour afficher une page générique error.html et une règle de redirection pour rediriger les erreurs 404 vers une page 404.html (sans le hashbang).
En ce qui concerne les erreurs interdites 403, je ne les laisse pas du tout se produire. Dans mon application, je considère que tous les fichiers dans le bucket hôte sont publics et je l'ai défini avec l' option tout le monde avec l' autorisation de lecture . Si votre site a des pages privées, laisser l'utilisateur voir la mise en page HTML ne devrait pas être un problème. Ce que vous devez protéger, ce sont les données et cela se fait dans le backend.
De plus, si vous possédez des actifs privés, comme des photos d'utilisateurs, vous pouvez les enregistrer dans un autre compartiment. Parce que les actifs privés nécessitent le même soin que les données et ne peuvent pas être comparés aux fichiers d'actifs utilisés pour héberger l'application.
la source
J'ai rencontré le même problème aujourd'hui, mais la solution de @ Mark-Nutter était incomplète pour supprimer le hashbang de mon application angularjs.
En fait, vous devez aller dans Modifier les autorisations , cliquer sur Ajouter plus d'autorisations , puis ajouter la bonne liste sur votre compartiment à tout le monde. Avec cette configuration, AWS S3 sera désormais en mesure de renvoyer une erreur 404, puis la règle de redirection interceptera correctement le cas.
Juste comme ça :
Et puis vous pouvez aller dans Modifier les règles de redirection et ajouter cette règle:
Ici, vous pouvez remplacer le nom d' hôte subdomain.domain.fr par votre domaine et le KeyPrefix #! / Si vous n'utilisez pas la méthode hashbang à des fins de référencement.
Bien sûr, tout cela ne fonctionnera que si vous avez déjà configuré html5mode dans votre application angulaire.
la source
La solution la plus simple pour faire fonctionner l'application Angular 2+ à partir d'Amazon S3 et des URL directes est de spécifier index.html à la fois comme documents d'index et d'erreur dans la configuration du compartiment S3.
la source
body
la réponse. Le code d'état sera 404 et cela nuira au référencement.body
si vous avez des scripts que vous importez dans lehead
ils ne fonctionneront pas lorsque vous frappez directement l'un des sous-itinéraires sur votre site Webcomme le problème est toujours là, j'ai pensé proposer une autre solution. Mon cas était que je voulais déployer automatiquement toutes les demandes d'extraction vers s3 pour les tester avant de les fusionner en les rendant accessibles sur [mon domaine] / pull-demandes / [numéro pr] /
(ex. Www.example.com/pull-requests/822/ )
À ma connaissance, aucun scénario de règles s3 ne permettrait d'avoir plusieurs projets dans un seul compartiment en utilisant le routage html5, alors que la suggestion la plus votée fonctionne pour un projet dans le dossier racine, mais pas pour plusieurs projets dans ses propres sous-dossiers.
J'ai donc pointé mon domaine vers mon serveur où la configuration nginx suivante a fait le travail
il essaie d'obtenir le fichier et s'il n'est pas trouvé suppose qu'il s'agit de la route html5 et essaie cela. Si vous avez une page angulaire 404 pour les itinéraires non trouvés, vous n'obtiendrez jamais à @not_found et vous obtiendrez une page 404 angulaire retournée au lieu de fichiers non trouvés, qui pourrait être corrigée avec une règle if dans @get_routes ou quelque chose.
Je dois dire que je ne me sens pas trop à l'aise dans le domaine de la configuration de nginx et de l'utilisation d'expressions rationnelles, d'ailleurs, j'ai réussi à le faire avec quelques essais et erreurs, alors que cela fonctionne, je suis sûr qu'il y a place à amélioration et s'il vous plaît partagez vos réflexions .
Remarque : supprimez les règles de redirection s3 si vous les aviez dans la configuration S3.
et btw fonctionne dans Safari
la source
Je cherchais le même genre de problème. J'ai fini par utiliser un mélange des solutions suggérées décrites ci-dessus.
Tout d'abord, j'ai un compartiment s3 avec plusieurs dossiers, chaque dossier représente un site Web react / redux. J'utilise également cloudfront pour l'invalidation du cache.
J'ai donc dû utiliser les règles de routage pour prendre en charge 404 et les rediriger vers une configuration de hachage:
Dans mon code js, j'avais besoin de le gérer avec une
baseName
configuration pour react-router. Tout d'abord, assurez-vous que vos dépendances sont interopérables, j'avais installé une versionhistory==4.0.0
incompatible avecreact-router==3.0.1
.Mes dépendances sont:
J'ai créé un
history.js
fichier pour l'historique de chargement:Ce morceau de code permet de gérer les 404 envoyés par le serveur avec un hachage, et de les remplacer dans l'historique pour charger nos routes.
Vous pouvez maintenant utiliser ce fichier pour configurer votre magasin et votre fichier racine.
J'espère que ça aide. Vous remarquerez qu'avec cette configuration, j'utilise un injecteur redux et un injecteur sagas homebrew pour charger javascript de manière asynchrone via le routage. Ne vous occupez pas de ces lignes.
la source
Vous pouvez maintenant le faire avec Lambda @ Edge pour réécrire les chemins
Voici une fonction lambda @ Edge fonctionnelle:
Dans vos comportements cloudfront, vous les modifierez pour ajouter un appel à cette fonction lambda sur "Viewer Request"
Tutoriel complet: https://aws.amazon.com/blogs/compute/implementing-default-directory-indexes-in-amazon-s3-backed-amazon-cloudfront-origins-using-lambdaedge/
la source
return callback(null, request);
Si vous avez atterri ici à la recherche d'une solution qui fonctionne avec React Router et AWS Amplify Console - vous savez déjà que vous ne pouvez pas utiliser les règles de redirection CloudFront directement car Amplify Console n'expose pas CloudFront Distribution pour l'application.
Cependant, la solution est très simple - il vous suffit d'ajouter une règle de redirection / réécriture dans Amplify Console comme ceci:
Voir les liens suivants pour plus d'informations (et la règle de copie de la capture d'écran):
la source
Je cherchais moi-même une réponse à cette question. S3 ne semble prendre en charge que les redirections, vous ne pouvez pas simplement réécrire l'URL et renvoyer silencieusement une ressource différente. J'envisage d'utiliser mon script de construction pour simplement faire des copies de mon index.html dans tous les emplacements de chemin requis. Peut-être que cela fonctionnera aussi pour vous.
la source
Juste pour mettre la réponse extrêmement simple. Utilisez simplement la stratégie d'emplacement de hachage pour le routeur si vous hébergez sur S3.
export const AppRoutingModule: ModuleWithProviders = RouterModule.forRoot (routes, {useHash: true, scrollPositionRestoration: 'enabled'});
la source