web-dev-qa-db-ja.com

URLの末尾から拡張子を削除し、末尾のスラッシュを強制する方法は?

現在のファイル構造の例:

example.com/foo.php  
example.com/bar.html  
example.com/directory/  
example.com/directory/foo.php  
example.com/directory/bar.html  
example.com/cgi-bin/directory/foo.cgi*  

HTML、PHP、CGIの拡張機能を削除し、URLの最後にスラッシュを強制的に追加したいと思います。したがって、次のようになります。

example.com/foo/  
example.com/bar/  
example.com/directory/  
example.com/directory/foo/  
example.com/directory/bar/  
example.com/cgi-bin/directory/foo/

解決策を17時間連続で検索し、さまざまなブログやフォーラムの数百ページ以上を訪問したため、非常にイライラしています。私は冗談ではありません。だから私は研究を行ったと思う。

ここに、私の.htaccessファイルにあるコードを示します。

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.html -f
RewriteRule ^(([^/]+/)*[^./]+)/$ $1.html
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]|/)$
RewriteRule (.*)$ /$1/ [R=301,L]

ご覧のとおり、このコードは.htmlを削除するだけです(これはもっと簡単にできると思うので、あまり満足していません)。 .htaccessを使用して拡張子を.htmlに変更すると、PHPファイルから拡張機能を削除できますが、それは私が望むものではありません。まっすぐに取り除きたいです。これは、私がどのようにすればよいかわからない最初のことです。

2番目は、実際には非常に迷惑です。上記のコードを含む私の.htaccessファイルは、.html/の後に入力されたすべての文字列にexample.com/directory/foo/を追加します。したがって、example.com/directory/foo/barと入力した場合(fooはファイルであるため、明らかに/barは存在しません)、ページが見つからないというメッセージを表示する代わりに、それをexample.com/directory/foo/bar.html/に変換してから、数秒間ファイルを検索し、その後、見つかりませんメッセージが表示されます。もちろん、これは悪い動作です。

したがって、もう一度、次のことを行うには.htaccessのコードが必要です。

  • 。html拡張子を削除
  • 。php拡張子の削除
  • 。cgi拡張子を削除
  • RLの最後にスラッシュを強制する
  • リクエストは正しく動作するはずです(ファイルまたはディレクトリがサーバーに存在しない場合、文字列に末尾のスラッシュや拡張子を追加しないでください)
  • コードはできるだけシンプルにする必要があります

@Kronbernkzion素晴らしい。私が今抱えている唯一の問題は、404が正しく機能していないようであり、本当のファンキーな場所に私を導き、絶対的な404リダイレクトを使用することさえできないことです。

ErrorDocument 404 http://www.google.com

これに出会いましたか?どうやってそれを乗り越えましたか?

404の書き換えとは別に、私が使用した完全なコードは次のとおりです。

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_URI} (.*)/$
RewriteCond %{REQUEST_FILENAME}\.html -f
RewriteRule (.*)/$ $1.html [L]

RewriteCond %{REQUEST_URI} (.*)/$
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule (.*)/$ $1.php [L]

RewriteCond %{REQUEST_URI} (.*)/$
RewriteCond %{REQUEST_FILENAME}\.cgi -f
RewriteRule (.*)/$ $1.cgi [L]

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.html -f [OR]
RewriteCond %{REQUEST_FILENAME}\.php -f [OR]
RewriteCond %{REQUEST_FILENAME}\.cgi -f
RewriteRule .* %{REQUEST_FILENAME}/ [R=301,L]
</IfModule>
7
Kronbernkzion

だから私はあなたが望むことをする一連の書き換えルールを書いたが、それは私のウェブサイトを完全に壊した。私はあなたが望むものがおそらくあなたが必要とするものではないことに気づきました。すべてのURLの末尾にスラッシュを追加すると、ファイル/fooではなくディレクトリのコンテンツリスト/foo/にアクセスしなくなるという点で、URLのセマンティクスが実際に混乱します。

例えば:

/mypage/mypage/に変更すると、おそらくbreak相対リンクになります。 JavaScriptファイル<script src="myscript.js">を参照する場合、/myscript.jsを探す代わりに、ブラウザは/mypage/myscript.jsを探します。 <script src="../myscript.js">を読み取るようにソースを変更する必要があります。1)作成者にとって意味がなく、2)スラッシュがない場合よりもlooksいように見えます。

参考のため:

RewriteCond %{REQUEST_FILE}\.html -f
RewriteRule (.*)$ $1.html [L]

RewriteCond %{REQUEST_FILE}\.php -f
RewriteRule (.*)$ $1.php [L]

RewriteCond %{REQUEST_FILE}\.cgi -f
RewriteRule (.*)$ $1.cgi [L]

変更onlyphp、cgi、およびhtml拡張機能がありますが、Apache2コンテンツネゴシエーション(MultiViewsを使用)を使用することをお勧めします。

編集:

元のコード。または少なくともその一部。私はそれを壊し、それから上記に切り詰めました、そして今、私は自分が何をしたかをかなり思い出すことができません。ただし、末尾の拡張子を削除する以外はすべて行います。

# This block adds the trailing slash
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond /your/web/directory%{REQUEST_URI}\.html -f [OR]
RewriteCond /your/web/directory%{REQUEST_URI}\.php -f [OR]
RewriteCond /your/web/directory%{REQUEST_URI}\.cgi -f
RewriteRule .* %{REQUEST_URI}/ [R=301,L]

# These blocks redirect /foo/ to /foo.html and so on
RewriteCond %{REQUEST_URI} (.*)/$
RewriteCond /your/web/directory%1\.html -f
RewriteRule (.*)/$ $1.html [L]

RewriteCond %{REQUEST_URI} (.*)/$
RewriteCond /your/web/directory%1\.php -f
RewriteRule (.*)/$ $1.php [L]

RewriteCond %{REQUEST_URI} (.*)/$
RewriteCond /your/web/directory%1\.cgi -f
RewriteRule (.*)/$ $1.cgi [L]

ご希望の場合は、azezera.comのmazinまでメールでお問い合わせください。

6
erjiang

マジン、助けてくれて正しい方向を見せてくれてありがとう!以下のコードは、.html、.php、および.cgi拡張子を削除し、URLの末尾にスラッシュを強制するために機能します。最終的な作業コードは次のようになります。

RewriteCond %{REQUEST_URI} (.*)/$
RewriteCond %{REQUEST_FILENAME}\.html -f
RewriteRule (.*)/$ $1.html [L]

RewriteCond %{REQUEST_URI} (.*)/$
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule (.*)/$ $1.php [L]

RewriteCond %{REQUEST_URI} (.*)/$
RewriteCond %{REQUEST_FILENAME}\.cgi -f
RewriteRule (.*)/$ $1.cgi [L]

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.html -f [OR]
RewriteCond %{REQUEST_FILENAME}\.php -f [OR]
RewriteCond %{REQUEST_FILENAME}\.cgi -f
RewriteRule .* %{REQUEST_FILENAME}/ [R=301,L]

私はこれが判明した方法に非常に満足しています。

私は50ドルのiTunesギフトカードを大きなものとしてMazinに送った感謝.

3
Kronbernkzion

RESTに準拠したURL実装に似たようなことをしようとしているように聞こえます。

私はこれをSOでカバーしているのを見たことがあります: https://stackoverflow.com/questions/395650/url-mapping-in-php

必要に応じて、上位2つのソリューションを適応できる場合があります。

1
Chris Thorpe

必要な各URLの正確な形式がわかっている場合は、かなり簡単です。ただし、どの拡張子を一致させる必要があるかわからない場合は、それは不可能だと確信しています。

たとえば、foo.htmlbar.phpがあり、/foo/がfoo.htmlに一致する必要があることと、/bar /が/bar.phpに一致する必要があることがわかっている場合は、それを実行できます。しかし、誰かが/cat.phpをアップロードし、誰かが/cat/を入力した場合-システムは/cat.htmlまたは/cat.phpに一致する必要があるかどうかを知りません-あなたはそれを伝える必要があります。 1つの拡張機能だけを扱っている場合、それはそれほど悪くはないでしょう。すべてのリクエストに追加することができます。

/foo//foo.htmlに書き換えるには、次のようにします。

RewriteRule (/foo/) /foo.html

かんたん

すべてのリクエストを単一の拡張機能に一致させたい場合は、次のようにします。

RewriteRule (/foo/)(.*)(/) /foo/$2.html

これにより、/foo/mypage//foo/mypage.htmlにマップされます(そして、私の給与グレードを超えるRegEx-fuを使用して、これをマルチレベルディレクトリに展開できます)。

今、私はそれがあなたが求めているものであることを実際には知らないので、これらのルールがうまくいかない場合は、私の答えにコメントするか、質問を更新してください。

-編集-

上記の私のコメントに対するあなたの反応に気づいただけです。 .htaccessには特定のファイルリクエストが存在するかどうかを確認する機能がないため、.htaccessでやりたいことを行う方法はありません。 /foo//foo.htmlまたは/foo.phpまたは/foo.cgiであることをどうやって知るのでしょうか?それを回避する唯一の方法は次のとおりです。

1)single.phpファイルを介してすべてのリクエストを漏斗し、ファイルの.phpまたは.htmlまたは.cgiバージョンが存在するかどうかを確認/確認する機能があり、リクエストをそのように転送します

2)すべての一意のファイルのエントリを含む.htaccessファイルを作成します

0
Mark Henderson