0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

apacheでmod_rewriteで一時的に変数使いたくてハマったお話

Posted at

結論

mod_rewriteで設定した環境変数にmod_rewriteでアクセスする場合、変数名の最初に'REDIRECT_'がつく

背景

laravelで動いているサービスでメンテナンスモードを追加したい。
laravelにメンテナンスモードの仕組みはあるけど、特定のapiだけはメンテナンスモード中でも使いたいとか、特定のIPからはメンテナンス中でも使えるようにしたいけど、URLにシークレットコードつけたりは難しいなどがあり、.htaccessをゴニョゴニョすることで対応しようとした。

条件

  • /api/aaa はメンテナンス中でも使いたい
  • それ以外のapiは403を返す
  • api以外のアクセスはccc.htmlを表示
  • favicon.icoは表示
  • ほんとはもうちょっと条件あったけど、例として簡単にした

とりあえすこんな感じで書いてみた

<IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
        Options -MultiViews -Indexes
    </IfModule>

    RewriteEngine On

    # aaa以外のapiは403 ・・・ ①
    RewriteCond %{REQUEST_URI} /api
    RewriteCond %{REQUEST_URI} !/api/aaa
    RewriteRule ^.*$ - [F,L]

    # API以外のアクセスはccc.htmlを表示 ・・・ ②
    RewriteCond %{REQUEST_URI} !/(api|favicon.ico|ccc.html)
    RewriteRule ^.*$ /ccc.html [L]

    ・・・
    
    # Send Requests To Front Controller... ・・・ ③
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [L]
</IfModule>

結果、/api/aaa以外のapiは403になったし、api以外はccc.htmlが表示された
しかし、/api/aaaにアクセスするとccc.htmlが返ってきた

③で/api/aaa が index.phpにrewriteされた後、また上から評価されて、②でapi以外なのでccc.htmlにrewriteされてしまった

②でindex.phpを対象外にすれば良さそうだけど、index.phpにアクセスされた場合に素通りしてしまう
rewriteする前のURLを判定できればなんとかなりそうだということで・・・

一時的に変数に元のURLを保持してみた

RewriteRule時のフラグのE or ENVでapacehの環境変数に値を設定できるらしい
RewriteCondでは%{ENV:・・・}でapacheの環境変数を使用できるらしい
ということで、③でindex.phpにrewrite時に元のURLを環境変数に設定しておいて、再評価時に②で/api/aaaからrewriteされたアクセスは除外すればいけそうかなとこんな感じで試してみた。

<IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
        Options -MultiViews -Indexes
    </IfModule>

    RewriteEngine On

    # aaa以外のapiは403 ・・・ ①
    RewriteCond %{REQUEST_URI} /api
    RewriteCond %{REQUEST_URI} !/api/aaa
    RewriteRule ^.*$ - [F,L]

    # API以外のアクセスはccc.htmlを表示 ・・・ ②
    RewriteCond %{REQUEST_URI} !/(api|favicon.ico|ccc.html)
    RewriteCond %{ENV:ORG_URI} !/api/aaa
    RewriteRule ^.*$ /ccc.html [L]

    ・・・
    
    # Send Requests To Front Controller... ・・・ ③
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [E:ORG_URI=%{REQUEST_URI},L]
</IfModule>

結果、/api/aaaにアクセスするとccc.htmlが帰ってきてしまう・・・
ログを出してみて確認すると、確かに③で環境変数ORG_URIに/api/aaaを入れているようだが、再評価時の②のORG_URIは空になっている??

結局・・・

調べてみると、どうやらmod_rewriteのEフラグで環境変数に設定したものは、mod_rewriteの変数ENV:で取得する場合は、頭に「REDIRECT_」がつくらしい!!

ということで、

<IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
        Options -MultiViews -Indexes
    </IfModule>

    RewriteEngine On

    # aaa以外のapiは403 ・・・ ①
    RewriteCond %{REQUEST_URI} /api
    RewriteCond %{REQUEST_URI} !/api/aaa
    RewriteRule ^.*$ - [F,L]

    # API以外のアクセスはccc.htmlを表示 ・・・ ②
    RewriteCond %{REQUEST_URI} !/(api|favicon.ico|ccc.html)
    RewriteCond %{ENV:REDIRECT_ORG_URI} !/api/aaa
    RewriteRule ^.*$ /ccc.html [L]

    ・・・
    
    # Send Requests To Front Controller... ・・・ ③
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [E:ORG_URI=%{REQUEST_URI},L]
</IfModule>

これで、/api/aaaは使えるようになった

参考サイト

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?