Pourquoi les ancres codées par URI ('#') provoquent 404, et comment traiter avec JS?

PrettyPhoto utilise des hashtags, mais s'ils sont encodés (à% 23), la plupart des navigateurs généreront une erreur 404. Cela a été discuté avant :

Vous obtenez une erreur 404 car la partie #callback ne fait pas partie de l'URL. C'est un marque-page utilisé par le navigateur, et il n'est jamais envoyé dans la requête au serveur. Si vous codez le hash, il devient une partie du nom du fichier.

  1. Pourquoi un hash deviendrait-il partie du fichier juste parce qu'il est codé par URI? N'est-ce pas un bug?

  2. Je demande parce que prettyPhoto utilise des hashtags et souffre du même problème. Je pense que l'ajout d'un '?' Avant que le hash soit la solution la plus élégante, je ne suis qu'une perte de la façon de le faire dans le code existant:

      Function getHashtag () {
     Url = location.href;
     Hashtag = url.indexOf ('# gallery')! == - 1)? DecodeURI (url.substring (url.indexOf ('# gallery') + 1, url.length)): false;
     Return hashtag;
     }
     Function setHashtag () {
     Si (typeofRel == 'indefini') retourne;  Location.hash = theRel + '/' + rel_index + '/';
     }
     Function clearHashtag () {
     Si (location.href.indexOf ('# gallery')! == - 1) location.hash = "";
     } 
  3. D'autres suggestions? Je vais chercher à peaufiner ma page 404, mais cela semble plutôt traiter un problème plutôt que de l'empêcher.

Merci!

EDIT: Puisque, évidemment, il n'y a rien de mal avec la façon dont prettyphoto gère ces hashes, j'ai fini par ajouter ces règles à mon serveur apache:

RewriteRule ^(.*).shtml(%23|#)$ /$1.shtml [R=301,NE,L] RewriteRule ^(.*).shtml([^g]+)gallery(.+)$ /$1.shtml#gallery$3 [R=301,NE,L] 

Ils ont réussi à gérer les cas où% 23 a causé des problèmes.

  1. Pourquoi un hash deviendrait-il partie du fichier juste parce qu'il est codé par URI? N'est-ce pas un bug?

Si vous indiquez votre navigateur sur http://example.com/index.html#title , le navigateur interprète ceci pour faire une requête pour le fichier index.html partir du serveur example.com . Une fois la demande terminée, le navigateur recherche un élément d'ancrage dans le document avec le nom de «titre» (c'est-à-dire mon titre).

Si vous indiquez à l' http://example.com/index.html%23title , le navigateur demande une demande pour le fichier index.html%23 de example.com , qui n'existe probablement pas sur le serveur, vous donnant un 404. Voir la différence?

Et ce n'est pas un bug. Cela fait partie d'un standard Internet mis à jour en 1998. Voir RFC 2396 . Citation:

Le caractère "#" est exclu car il est utilisé pour délimiter un URI à partir d'un identificateur de fragment dans les références URI (Section 4).

Quant aux 2 et 3, il n'y a pas assez de contexte dans votre exemple de code pour indiquer ce que vous essayez de faire. Comment appelez-vous votre code? Qu'est-ce que vous essayez de faire avec prettyphoto qui ne fonctionne pas? Essayez-vous de rediriger vers une photo ou une galerie spécifique à partir d'un clic d'utilisateur ou d'un autre événement javascript? Essayez-vous d'ouvrir la galerie lorsque quelqu'un visite une page particulière?

J'ai vérifié la question liée avec twitter / oauth, mais je ne vois pas comment cela s'inscrit dans le code que vous avez fourni. J'ai commencé à frapper à Prettyphoto aussi, mais je ne vois pas comment votre code se rapporte non plus à cela.

Au lieu de changer votre page 404, peut-être que vous avez besoin d'une règle de réinitialisation du gestionnaire de code ou du serveur qui prend des requêtes non trouvées avec un %23 et réoriente l'utilisateur vers l'URL décodée. Cela pourrait avoir des inconvénients, mais ce serait assez élégant si vous prenez des demandes d'autres sources que vous ne pouvez pas contrôler. Quel est votre environnement de serveur? (Langue, technologie de serveur, propriétaire de la machine, etc.)

Je serais heureux de mettre à jour ma réponse avec une solution ou un travail pour vous.

Pour répondre au numéro 1)

Cela deviendrait une partie de l'URL car ce n'est plus un jeton que le navigateur / serveur / etc sait comment analyser.

Ce que je veux dire, c'est que "?" Joue un rôle important dans les URL – le serveur sait séparer ce qui précède de ce qui se passe. Le navigateur n'a pas besoin de se soucier de ce qui est ou n'est pas dynamique dans l'URI – c'est tout important (bien que JavaScript sépare les valeurs de l'objet de localisation).

Le navigateur n'émettra pas "# ……" au serveur, car le hashtag possède des connotations spéciales pour le navigateur.

Cependant, si vous échappez à ce hash en JavaScript, le navigateur n'hésitera pas à envoyer cette chaîne échappée au serveur en tant que valeur littérale.

Pourquoi n'est-ce pas? Si votre requête de recherche requiert légitimement un caractère hash (vous effectuez une demande POST sur un mur de Facebook, et vous soumettez un numéro de téléphone), vous seriez foutu. Ou vous faites une recherche GET d'un certain nombre sur 411.com ou quoi que ce soit, et ils n'ont pas vraiment pensé à leur application.

Le problème est que le serveur ne comprend pas que la valeur échappée doit se tenir séparément de l'url, si elle se produit dans le chemin réel.

Il doit accepter les caractères échappés, sinon les espaces (% 20) et les autres caractères quotidiens, qui sont par ailleurs valides dans les noms de fichiers / chemins / requêtes / valeurs, poseraient des problèmes.

Donc, si vous cherchez:

 //mysite.gov.on.ca/path/to/file.extension%23action%3Dfullscreen 

En vérité, vous devez sûrement 404.

Il y a quelques choses que vous pourriez faire, je suis certain. Le premier serait dans Apache, ou ce que vous voulez faire, vous pouvez écrire un RegEx qui correspond à n'importe quelle URL jusqu'au premier "% 23", en supposant qu'il n'y ait pas de "?" préalablement.

Les implémentations moins égarées peuvent impliquer de déterminer s'il existe un moyen d'échapper au "#" qui est compatible avec le plug-in.

Google, par exemple, utilise une stratégie "hash-bang" ("#!") Où elle demande que les URL soient soumises de cette façon, pour savoir si elles doivent ou non coder.

D'autres options pourraient consister à vérifier un caractère "#" à l'aide de url.indexOf("#"); Et diviser l'URL au hash, et en soumettant la partie valide.

Tout cela se résume à ce que vous essayez d'accomplir – je peux indiquer pourquoi c'est un problème, mais la meilleure façon de faire un problème ne dépend pas de ce que vous essayez de faire, comment vous essayez Pour le faire, et ce qui est permis dans le contexte dans lequel vous travaillez.