2010-03-26 3 views
5

J'utilise apache/mod_rewrite pour réécrire les URL mais j'ai des problèmes avec le signe plus.Apache mod_rewrite% 2B et les signes plus (+)

Avec la règle suivante ..

RewriteRule ^/(.+[^/])/?$ http://localhost:8080/app/home?tag=$1 [P,L] 

deux:

http://localhost/1+1 and http://localhost/1%2B2 
fin

comme

uri=http://localhost:8080/app/home, args=tag=1+2 

Ainsi, dans les deux cas, l'application se traduit par le signe plus dans un espace si il ne peut plus différencier les espaces et les signes plus.

Si j'utilise le « B » drapeau, puis dans les deux cas, les signes + sont convertis en% 2B et l'application se termine avec le même problème, mais inversé (les deux espaces et les signes plus sont des signes plus)

Existe-t-il un moyen d'obtenir que apache échappe correctement% 2B dans un signe plus et pas un espace?

J'ai lu quelque chose à propos de mod_security mais je n'utilise pas cela donc je ne suis pas sûr s'il y a un autre mécanisme de sécurité qui cause cela?

Toute aide serait grandement appréciée!

Répondre

2

Non, ce n'est pas tout à fait la même chose que la question référencée. Le problème ici est spécifiquement des signes plus et la réponse à Apache: mod_rewrite: Spcaes & Special Characters in URL not working ne répond pas à cela.

Il y a aussi un problème avec les barres obliques, pour lesquelles voir http://httpd.apache.org/docs/current/mod/core.html#allowencodedslashes (mais vous avez besoin d'accéder à la configuration d'Apache pour cela - .htaccess ne le fera pas).

En fait c'est impossible à faire en utilisant une règle de réécriture seule. Apache décode l'URL avant de le mettre par réécriture, mais il ne comprend pas des signes plus: ne fournirions pas http://example.com/a+b.html un fichier appelé

« un b.html ».

Les signes plus sont décodées par PHP dans le tableau $ _GET (ou quel que soit le mécanisme de la langue pertinente est) pour les chaînes de requête, car les gestionnaires de formulaire dans les navigateurs les mettre. Alors Apache se traduira% 2B à + avant d'appliquer la réécriture, et laissez + lui-même seul, ce qui signifie que vous ne pouvez pas faire la différence.

Bien sûr, on pourrait soutenir que + utilisé comme espace est tout simplement invalide dans de telles URL et que l'on devrait utiliser seulement% 20. Cependant, si vous ne pouvez pas les générer, vous devez les voir. Les navigateurs ne les généreront pas automatiquement.

La réponse est DIY, et à bien des égards, il est plus prévisible et plus simple.

RewriteRule * index.php [L]

tout se transforme en index.php Par conséquent et il y a aucune tentative de construction d'une chaîne de requête. Si vous souhaitez exclure certains motifs, par ex.ceux avec des barres obliques, ou lorsqu'un fichier explicite existe, les modifications évidentes s'appliquent. par exemple. RewriteCond% {REQUEST_FILENAME} -f

Puis, dans index.php

$ uri = substr ($ _ SERVER [ 'REQUEST_URI'], 1)!; // supprime le slash initial

$ qmpos = strpos ($ uri, '?'); // Y at-il un point d'interrogation? Si oui où

if ($ qmpos! == FALSE) {$ uri = substr ($ uri, 0, $ qmpos); } // seulement le bit avant q.m.

$ décodé = urldecode ($ uri); // décode la partie avant l'URL

if (! vide ($ décodé)) {$ _GET ['args'] = $ décodé; } // ajouter résultat à $ _GET

qui décode la demande initiale (hors barre oblique - serait légèrement différente si vous êtes plus profondément une hiérarchie, mais le principe est le même - et l'exclusion de tout chaîne de requête supplémentaire), et décode le paramètre args selon les règles normales de PHP et le place dans $ _GET afin que vous puissiez le traiter avec le reste des paramètres de chaîne de requête $ _GET de la manière habituelle.

Je crois que cela devrait fonctionner pour les URL vides (http://example.com/) ou ceux qui n'ont une chaîne de requête (http://example.com/?foo=1), ainsi que le cas simple (http://example.com/bar) et le cas d'une chaîne de requête et (http://example.com/bar?foo=1). Il ne fait aucun doute que des approches similaires fonctionneront pour d'autres langues.

Dans votre cas particulier, vous ne voulez pas du tout décoder les plus dans le PHP. C'est bien, utilisez plutôt rawurldecode, qui ne fait pas de plus.

+0

Merci; C'est le seul article que j'ai trouvé qui réponde correctement au problème des signes + dans la partie locale de l'URL. La phrase clé dans la réponse ci-dessus est "En fait, il est impossible d'utiliser une règle de réécriture seule Apache décode l'URL avant de la réécrire, mais ne comprend pas les signes plus". – fooquency