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.

  • htaccess rewriterule leading slash
  • Bloquer les requêtes des robots par motif dans apache avec mod_rewrite. mod_rewrite ne fonctionne pas
  • Comment puis-je rediriger toute ServerAlias ​​vers le ServerName correspondant?
  • La redirection d'URL d'Apache peut-elle envoyer une request à l'URL originale et à l'URL réécrit?
  • Configuration d'Apache, Tomcat, mod_jk et mod_rewrite pour servir Tomcat depuis le niveau supérieur
  • mod_rewrite et% caractère
  • Apache ProxyPass / RewriteRule avec p flag: Ne returnnez aucun contenu lorsque la réponse a un type de contenu en plusieurs parties, c'est-à-dire les images
  • .htaccess envoie des requêtes à l'index.php d'un sous-dossier
  • mod_rewrite à la page avec authentification HTTP
  • Comment redirect vers une page donnée en fonction des parameters régionaux de l'user?
  • J'utilise mod_rewrite et j'utilise une règle de réécriture, existe-t-il un moyen pour moi d'get l'URL dans le côté du server de la barre d'adresse?
  • Les astuces du serveur de linux et windows, tels que ubuntu, centos, apache, nginx, debian et des sujets de rĂ©seau.