web-dev-qa-db-ja.com

.htaccessでの301リダイレクトと内部書き換えの両方の処理

私は自分のウェブサイトで3つのことをしたいです:

  • ユーザーがHTTPバージョンにアクセスするときに、301を使用するユーザーをサイトのHTTPSバージョンにリダイレクトします
  • URLにwwwを入力すると、301のユーザーをサイトの「no-www」バージョンにリダイレクトします
  • サイレントに(または内部的に)/*/index.php?p=*にリダイレクトします(フレームワークを使用しているため)。 (または、「視覚的に」/index.php?p=*/*にリダイレクトしてから、内部で/*/index.php?p=*にリダイレクトします...)

これが私の現在の.htaccessです:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /

RewriteCond %{HTTP_Host} ^www\.(.*)$ [NC]
RewriteRule (.*) https://%1/$1 [R=301]

RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_Host}%{REQUEST_URI} [R=301]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.+) index.php?p=$1 [QSA]
</IfModule>

ただし、この構成を実行しているとき、301リダイレクトが機能していません。具体的には、301コードは実際にはクライアントに送信されますが、Location:ヘッダーは送信されません。

$ curl http://mywebsite.com/path -I
HTTP/1.1 301 Moved Permanently
Date: Thu, 23 Apr 2020 19:03:57 GMT
Server: Apache/2.4.38 (Debian)
Set-Cookie: ci_session=q24j0enjrskagec2fggi256bpg5fsvs6; expires=Thu, 23-Apr-2020 20:39:57 GMT; Max-Age=7200; path=/; HttpOnly
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Content-Type: text/html; charset=UTF-8

index.phpに関するブロックを他の2つのブロックの前に配置しようとすると、HTTPSとwwwリダイレクトは機能しますが、Location:ヘッダーはページを処理するときに奇妙な動作をします。

λ curl http://mywebsite.com/fr/salon -I
HTTP/1.1 301 Moved Permanently
Date: Thu, 23 Apr 2020 19:09:03 GMT
Server: Apache/2.4.38 (Debian)
Location: https://mywebsite.com/fr/salon?p=fr/salon
Content-Type: text/html; charset=iso-8859-1

(また、奇妙な理由で、文字セットが変更されたことがわかります)

3つのリダイレクトを機能させるために、ルールに加える必要のある変更は何ですか?
ありがとうございました!

1
Ailothaen
RewriteCond %{HTTP_Host} ^www\.(.*)$ [NC]
RewriteRule (.*) https://%1/$1 [R=301]

RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_Host}%{REQUEST_URI} [R=301]

両方のリダイレクトにLlast)フラグがありません。 Lフラグがないと、処理が続行され、その後の内部書き換えによって捕捉されます。

例えば:

RewriteRule (.*) https://%1/$1 [R=301,L]

PDATE:後の書き換えにもLフラグを厳密に含める必要があります。これが最後のRewriteRuleである場合でも、厳密には問題になりません。ただし、後でルールを追加する場合は、それが重要になる可能性があります。

または、「視覚的に」/index.php?p=*/*にリダイレクトする

この部分は、oldindex.php?p= URLが検索エンジンによってインデックス付けされているか、サードパーティによってリンクされている既存のURL構造を変更する場合にのみ厳密に必要です。

ここで重要な点は、書き換えられたURLがリダイレクトされないようにすることで、潜在的なリダイレクトループを回避することです。これを行うには、REDIRECT_STATUS環境変数(最初のリクエストでは空で、最初の書き換えが成功した後の200 OK HTTPステータスのように "200"に設定される)をチェックします。

たとえば、before既存のリダイレクトの直後、RewriteBaseディレクティブの直後に、次のような操作を実行して、/index.php?p=*/*に外部リダイレクトできます。 :

RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} ^p=([^&]*)
RewriteRule ^index\.php$ https://example.com/%1 [QSD,R=302,L]

リクエストからクエリ文字列(つまり、p=* URLパラメータ)を削除するには、QSD(クエリ文字列の破棄)フラグ(Apache 2.4+)が必要です。これは、パススルーする必要のある他のURLパラメータがないことを前提としています-それらはすべて破棄されます。

これは、p URLパラメータが常にクエリ文字列の先頭にあることも前提としています(書き換えによる)。

substitution文字列に絶対URLを含めることで、HTTPまたはwwwサブドメインの要求に関連するセカンダリリダイレクトを回避できます。

これは現在302(一時的)リダイレクトであることに注意してください。潜在的なキャッシュの問題を回避するために、301(永続的な)リダイレクトに変更する前に、最初に302でテストすることをお勧めします。

1
MrWhite
 
 RewriteEngine On 
 RewriteCond%{HTTPS} off [OR] 
 RewriteCond%{HTTP_Host} ^ www \。 [NC] 
 RewriteCond%{HTTP_Host} ^(?: www \。)?(。+)$ [NC] 
 RewriteRule ^ https://%1%{REQUEST_URI} [L、 NE、R = 301] 
 
0
Putter.Network