質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Next.js

Next.jsは、Reactを用いたサーバサイドレンダリングなどを行う軽量なフレームワークです。Zeit社が開発しており、nextコマンドでプロジェクトを作成することにより、開発環境整備が整った環境が即時に作成できます。

mod_rewrite

ApacheウェブサーバーのためのURL書き換えモジュールです。主にプリティーURLに使われていますが、同様に単純置換を超えた、多様なタスクの処理能力や柔軟性があります。

Apache

Apacheは、Apache HTTP Serverの略で、最も人気の高いWebサーバソフトウェアの一つです。安定性が高いオープンソースソフトウェアとして商用サイトから自宅サーバまで、多くのプラットフォーム向けに開発・配布されています。サーバーソフトウェアの不具合(NCSA httpd)を修正するパッチ(a patch)を集積、一つ独立したソフトウェアとして開発されました。

WordPress

WordPressは、PHPで開発されているオープンソースのブログソフトウェアです。データベース管理システムにはMySQLを用いています。フリーのブログソフトウェアの中では最も人気が高く、PHPとHTMLを使って簡単にテンプレートをカスタマイズすることができます。

.htaccess

Apacheウェブサーバーにおいて、ディレクトリ単位で設置及び設定を行う設定ファイルを指します。

Q&A

0回答

2628閲覧

Apache で Trailing Slash なしでアクセスできるようにする方法

yuuAn

総合スコア44

Next.js

Next.jsは、Reactを用いたサーバサイドレンダリングなどを行う軽量なフレームワークです。Zeit社が開発しており、nextコマンドでプロジェクトを作成することにより、開発環境整備が整った環境が即時に作成できます。

mod_rewrite

ApacheウェブサーバーのためのURL書き換えモジュールです。主にプリティーURLに使われていますが、同様に単純置換を超えた、多様なタスクの処理能力や柔軟性があります。

Apache

Apacheは、Apache HTTP Serverの略で、最も人気の高いWebサーバソフトウェアの一つです。安定性が高いオープンソースソフトウェアとして商用サイトから自宅サーバまで、多くのプラットフォーム向けに開発・配布されています。サーバーソフトウェアの不具合(NCSA httpd)を修正するパッチ(a patch)を集積、一つ独立したソフトウェアとして開発されました。

WordPress

WordPressは、PHPで開発されているオープンソースのブログソフトウェアです。データベース管理システムにはMySQLを用いています。フリーのブログソフトウェアの中では最も人気が高く、PHPとHTMLを使って簡単にテンプレートをカスタマイズすることができます。

.htaccess

Apacheウェブサーバーにおいて、ディレクトリ単位で設置及び設定を行う設定ファイルを指します。

0グッド

0クリップ

投稿2021/04/16 06:10

編集2021/04/21 01:27

前提

現在 Vercel (Next.js) → Apache → Wordpress という構成でサーバー構築を行っています。

Vercel には example.com のドメインが割り当てられていて、Wordpress 側には b.example.com のドメインが割り当てられているとします。
クライアントは https://example.com にアクセスし、直接 https//b.example.com にアクセスすることはありません。
また、セキュリティ上アクセスできないように設定しています。

クライアントから https://example.com にアクセスがあった場合、ほとんどの場合は Next.js からの応答を返すのですが、特定のパス https://example.com/blog 以下にアクセスがあった場合のみ、Next.js から Wordpress にリクエストを転送し、Wordpress のレスポンスを、Next.js がクライアントに転送して返します。
つまり、この場合のみ、Vercel (Next.js) はリバースプロキシとして振る舞います。

Apache などで構築したリバースプロキシの場合、転送時にリクエストの URL (Host ヘッダ) を書き換えるだけでなく、レスポンスの URL (Location ヘッダ) も書き換えてくれるのですが、Next.js はそれをやってくれません。

起こっていること

前述の前提のため、Apache 側でリダイレクトが発生すると、リダイレクト先の URL が https://b.example.com/blog になってしまいます。
クライアントから直接 https://b.example.com にアクセスすることはない前提なので、これだとセキュリティの設定によって、エラーになってしまいます。

実現したいこと

Apache で発生するリダイレクトを発生しないようにするか、リダイレクト先をドメインを含まないパスのみにするか、リダイレクト先のドメインを example.com に変更するかして、エラーが発生しないようにしたいです。

調べてわかったこと

Apache の挙動

Apache でリダイレクトが発生する理由は、Trailing Slash で、mod_dir が発生させていました。
具体的には、https://example.com/bloghttps://b.example.com/blog/ のようなリダイレクトを発生させています。

試しに DirectorySlash Off を設定すると、リダイレクトは発生しなくなります。

mod_dir では、リダイレクトの細かい設定はできないらしく、もしやりたい場合は mod_rewrite でやることになりそうです。

Trailing Slash の扱い

Next.js では Trailing Slash を付けるか付けないかのどちらかの設定しかできないらしく、現在ビジネス上の都合により付けない設定になっているため、Next.js で Trailing Slash が外され、Apache で付けられるということになってしまっています。

クライアントが https://example.com/blog/ にアクセスすると、Next.js が /blog へのリダイレクトを返し、それを受けてクライアントが https://example.com/blog にアクセスすると、今度は Apache が https://b.example.com/blog/ へのリダイレクトを返します。

リダイレクト

Next.js では以下のようなリダイレクトレスポンスを返します。

$ curl -I https://example.com/blog/ HTTP/2 308 date: Thu, 15 Apr 2021 06:33:51 GMT content-type: text/plain location: /blog refresh: 0;url=/blog server: Vercel x-vercel-id: hnd1::cmlcm-xxxxxxxxxxxxx-xxxxxxxxxxxx strict-transport-security: max-age=63072000 cache-control: s-maxage=0

これにはドメインが含まれないので、Apache 側でもこのようなリダイレクトができればそうしたいです。

試したこと

解決に向けて、いくつかのプランを考え、それぞれ調べて試してみました。
このうちのどれかでも、別の方法でもいいので、解決方法がわかる方がいらっしゃいましたらご教授ください。

案 1. Next.js でレスポンスの location のドメインを書き換える

Apache でリバースプロキシを立てたときのように、Next.js でレスポンスの location ヘッダーのドメインを書き換えられればいいのですが、方法を見付けられませんでした。

それと、そうすると Next.js が /blog にリダイレクトし、続いて Apache が /blog/ にリダイレクトし、更に Next.js が……と、無限ループになってしまうので、この方法は断念しました。

案 2. Apache が返すリダイレクト先をパスのみにする

Apache が返すリダイレクトレスポンスを、Next.js が返すものと同じように、ドメインを含まない /blog/ のみにすれば、b.example.com がクライアントに伝わることもないと思ったのですが、こちらも無限ループが発生してしまいます。

案 3. 特定のパスのみ Trailing Slash を付ける

Next.js で、特定のパスのみ、Trailing Slash を付けるという設定ができればいいと思って調べたのですが、方法を見つけられませんでした。

もしこれが実現できたら、Next.js 側で必ず Trailing Slash が付与されるため、Apache が Trailing Slash のためにリダイレクトすることはなくなります。

ちなみに、Vercel には Trailing Slash について何もしないという設定があるのですが、
Next.js には Trailing Slash を付けるか付けないかのどちらかのオプションしかなさそうでした。

実現できたらこの方法が一番副作用が少なくてよいのですが。

案 4. Apache にリクエストを転送する際に Trailing Slash を付ける

Next.js に来たアクセスを Apache に転送する際に、Trailing Slash を付けられないかと思ったのですが、Wordpress は管理画面などでファイル名のみを指定した相対リンクが作られるので、Trailing Slash なしだとリンク先が変わってしまい、ダメでした。
現在のアドレスと相対パスから、絶対パスを生成するのはブラウザなので、Next.js の裏側でだけ Trailing Slash を付けても意味がありません。

一応試した方法を書いておきます。

現在の Next.js の next.config.js の設定は以下のようになっています。

js

1module.exports = { 2 async rewrites() { 3 return [ 4 { source: '/blog/:path*', destination: 'https://b.example.com/blog/:path*' } 5 { source: '/:path*', destination: '/:path*' }, 6 ]; 7 }, 8};

これに対して、単純に destination:path* の後ろに / を付けてみたのですが、ファイルにも / が付いてしまい、うまくいきませんでした。
例えば、app.cssapp.css/ になってしまいました。

:path* の部分をもう少し詳細に設定する方法があればとも思ったのですが、前述の相対パスの問題があったため諦めました。

案 5. Apache & Wordpress で Trailing Slash なしを受け入れる

Apache で Trailing Slash を付けるためのリダイレクトをやめて、Trailing Slash が無くてもリダイレクトせず、コンテンツを返すようにする。

まず、Apache ではリダイレクトをしてほしくないので、httpd.confDirectorySlash Off を設定し、Trailing Slash のためのリダイレクトを停止させます。

Wordpress のトップページと管理画面のトップページ以外は、Wordpress の設定を変えることで、リダイレクトせずにコンテンツを返すようにできました。
これらのページへのアクセスは、mod_rewrite で index.php に渡されるので、PHP 側でよしなにできます。

もし クライアントが Trailing Slash を付けてアクセスした場合も、Next.js が取ってくれるので、Apache 側は気にしなくて済みます。

しかし、トップページと管理画面のトップページは 403 になってしまいました。

もしかしたら他は mod_rewrite によって index.php へのアクセスに変わっているが、ディレクトリへのアクセスは、Apache の DirectoryIndex によって処理されているからなのかもしれません。

403 のとき、Apache のエラーログには以下のような出力がありました。

[Thu Apr 15 03:05:39.770634 2021] [autoindex:error] [pid 15756:tid 139987826042624] [client 10.0.0.1:48594] AH01276: Cannot serve directory /var/www/html: No matching DirectoryIndex (none) found, and server-generated directory index forbidden by Options directive

なお、.htaccess は Wordpress によって以下のように設定されています。

htaccess

1# BEGIN WordPress 2# "BEGIN WordPress" から "END WordPress" までのディレクティブ (行) は 3# 動的に生成され、WordPress フィルターによってのみ修正が可能です。 4# これらのマーカー間にあるディレクティブへのいかなる変更も上書きされてしまいます。 5<IfModule mod_rewrite.c> 6RewriteEngine On 7RewriteBase /blog/ 8RewriteRule ^index.php$ - [L] 9RewriteCond %{REQUEST_FILENAME} !-f 10RewriteCond %{REQUEST_FILENAME} !-d 11RewriteRule . /blog/index.php [L] 12</IfModule> 13 14# END WordPress

mod_rewrite で /blog/hoge/index.php に渡すことができているので、同じようにして /blogindex.php に渡すことができそうな気がするのですが、mod_rewrite に詳しくなく、やり方がわかりません。

ただ、この方法でうまくいったとしても、他の案と同じように、リンク先が相対パスになってるリンクは機能しません。

いくつか案を考えてそれぞれ試してみましたが、問題なく解決できそうなのは 案 3. だけでした。

補足情報(FW/ツールのバージョンなど)

nameversion
Next.js10.0.9
Apache2.4.39
PHP7.3.5
Wordpress5.5.3

Wordpress 側は既存のものを流用しているためバージョンが古めです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問