Règles HTTPS / HTTP mod_rewrite, interaction étrange avec l'index CMS ultérieur.php réécrit

Avec la réécriture ci-dessous dans htaccess, comme prévu , cette requête HTTPS n'est pas réécrite:

https://example.com/system/anything

N'est pas réécrit à

http://example.com/system/anything

Mais, de façon inattendue, cette demande HTTPS est réécrit:

https://example.com/preview/anything

Est réécrit à

http://example.com/index.php/preview/anything

Pourquoi est-ce?

Quelques autres faits / observations:

/system/ est un chemin réel sur le serveur. Mais /preview/ n'est pas un chemin réel – c'est un segment d'URL qui a un sens dans le CMS, par exemple, /index.php/preview/anything , le CMS reçoit la demande de l'URL /preview/anything .

Les autres URL non-système se réécrivent correctement (de HTTPS vers HTTP) et correctement, passent à index.php. Par exemple,

https://example.com/real

Est réécrit à

http://example.com/real

Voici le bloc complet de règles:

  <IfModule mod_rewrite.c> RewriteEngine On RewriteBase / # Force HTTPS for System URLs RewriteCond %{REQUEST_URI} ^/system(.*)$ [NC] RewriteCond %{HTTPS} !=on RewriteRule ^(.*)$ "https://example.com/$1" [R=301,L] # Force HTTP for Other URLs, but not: system or preview RewriteCond %{REQUEST_URI} !^/(system|preview)/(.*)$ [NC] RewriteCond %{HTTPS} =on RewriteRule ^(.*)$ "http://example.com/$1" [R=302,L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ /index.php/$1 [L] </IfModule> 

Tout aperçu de pourquoi /preview/ bénéficie d'un traitement étrange?


Ajouté: Notez que /preview/anything obtient une redirection 302 vers /index.php/preview/anything – et c'est une grande partie de ce qui semble si étrange / inattendu. Il ne devrait pas être une redirection dans la règle finale, juste une réécriture.

4 Solutions collect form web for “Règles HTTPS / HTTP mod_rewrite, interaction étrange avec l'index CMS ultérieur.php réécrit”

Est-ce que ces règles de réécriture dans un fichier .htaccess ? Dans ce cas, le drapeau [L] ne fait pas ce que vous en pensez – il arrête le traitement du jeu de règles actuel, mais la requête est ensuite traitée par Apache à nouveau, en utilisant .htaccess fichiers .htaccess appropriés pour l'URI réécrit, donc vos règles peuvent être Exécuté à nouveau. Cela ne se produit pas pour les règles qui sont dans le fichier de configuration Apache (et non dans une section <Directory> ) – dans ce cas, le drapeau [L] est traité comme prévu.

Pour votre exemple, https://example.com/preview/anything est en interne réécrit dans https://example.com/index.php/preview/anything par la troisième règle; Cependant, afin de traiter cette requête, Apache doit lire à nouveau le fichier .htaccess – et cette fois, l'URI correspond à votre deuxième règle, qui renvoie une redirection 302 .

Apache 2.4.x prend en charge le drapeau [END] qui arrête ces boucles de réécriture, contrairement à [L] ; Les solutions pour les versions antérieures d'Apache sont plus complexes.

Si vous souhaitez vous assurer que Apache ne fait qu'une seule passe sur vos règles de réécriture, vous pouvez ajouter la règle suivante avant toutes les autres:

 RewriteCond %{ENV:REDIRECT_STATUS} !="" RewriteRule ^ - [L] 

Sur la première passe REDIRECT_STATUS sera vide; Sur la deuxième passe, il aura une valeur non vide (généralement 200 ), et la règle correspondra et réarrêtera réellement les réécritures.

Dans le cas où une telle règle n'est pas appropriée (par exemple, dans certains cas, vous devez gérer les URI réécrits sur la deuxième passe), vous pouvez définir une variable d'environnement dans des règles qui devraient être vraiment définitives:

 RewriteRule ^(.*)$ /index.php/$1 [L,E=FINISH:1] 

Et ajoutez la règle suivante avant toutes les autres:

 RewriteCond %{ENV:REDIRECT_FINISH} !="" RewriteRule ^ - [L] 

Notez que pendant la deuxième passe, Apache prépare REDIRECT_ aux noms de variables d'environnement qui ont été définis lors de la première passe, vous devez donc définir FINISH , mais testez REDIRECT_FINISH .

Alternativement, vous pouvez essayer de modifier vos conditions d'appariement afin que les URI de seconde passe modifiés sur la première passe ne correspondent pas (par exemple, insérez (index\.php/)? Dans le regexp dans la deuxième règle).

Cela ressemble à la dernière règle qui consiste à introduire une redirection absolue en http lorsque cette opération est en cours, peut-être en raison d'un bug ou d'une fonctionnalité dans Apache ou mod_rewrite.

Que diriez-vous de vous diviser en deux règles avec une condition supplémentaire?

Essaye ça:

 RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{HTTPS} =off RewriteRule ^(.*)$ http://example.com/index.php/$1 [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{HTTPS} =on RewriteRule ^(.*)$ https://example.com/index.php/$1 [L] 

Le schéma http (au lieu de https ) vous dérange-t-il? Dans l'affirmative, vous devriez consulter la directive RewriteBase .

Du document mod_rewrite :

La directive RewriteBase spécifie le préfixe d'URL à utiliser pour les directives RewriteRule par répertoire (htaccess) qui remplacent un chemin relatif.

Cette directive est requise lorsque vous utilisez un chemin relatif dans une substitution dans le contexte de chaque répertoire (htaccess) (…)

Je ne pense pas que vous ayez besoin du '(. *) $' À la fin des instructions RewriteCond, car vous n'utilisez pas les données capturées n'importe où. Vous pouvez simplifier ces 2:

 RewriteCond %{REQUEST_URI} ^/system [NC] 

Et RewriteCond% {REQUEST_URI}! ^ / (Système | aperçu) / [NC]

Ce que je recommande également, c'est de lancer RewriteLog et de définir RewriteLogLevel pour voir exactement ce que fait Apache par requête. Avec apache 2.2 ou moins, ce serait:

 RewriteLog /var/log/apache2/rewrite.log RewriteLogLevel 7 

Vous devriez voir étape par étape exactement ce qui correspond et quelle action a pris apache.

  • Utiliser Apache httpd pour redirect le path du context?
  • Comment redirect le sous-domaine vers le domaine avec le sous-domaine comme paramètre
  • Réécrire sur https sans certificate?
  • Enstringment.htaccess renommer les règles - la directive est-elle nécessaire?
  • mod_rewrite dans le file .htaccess pour la première partie de pathement inconnue
  • Conversion spéciale de protection nginx hotlink de la règle d'application Apache .htaccess
  • Pourquoi l'logging de la réécriture dans .htaccess ne fonctionne-t-il pas?
  • Utilisation de mod_rewrite pour supprimer PATH_INFO de l'URL
  • .htaccess RewriteRule ne se partage pas où j'aimerais
  • Est-ce que les conditions de réécriture de modulation de court-circuit d'apache
  • Mod_rewrite change de cas même s'il ne correspond pas RewriteCond?
  • Les astuces du serveur de linux et windows, tels que ubuntu, centos, apache, nginx, debian et des sujets de rĂ©seau.