WebServer へのリクエスト情報から動的に BaseURL を決定する方法(Apache 編)
ここでは、WebServer(Apache)へのリクエスト情報から BaseURL を動的に決定する方法を BaseUrlProvider のサンプル実装、Apache との連携例と共に紹介します。
製品標準の設定では、テナント一つにつき、一つの BaseURL のみが設定可能ですが、BaseUrlProvider インタフェースを実装することで、複数の BaseURL を持たせることができます。
BaseUrlProvider は intra-mart Accel Platform 2014 Summer (Honoka) から導入されたインタフェースです。
したがって、2014 Summer (Honoka) 以降で使用可能です。
WebServer が IIS の場合はこちら
図のようにクライアントから WebServer へアクセスする URL の情報を利用して、WebServer(Apache)で BaseURL を作成します。
さらに、WebServer で作成した BaseURL を HTTP Header に追加して、intra-mart AccelPlatform(Resin)へ渡します。
intra-mart AccelPlatform では、BaseUrlProvider を用いて HTTP Header を確認し、渡された BaseURL を利用します。
注意事項
- IMBox の 通知情報, IM-Workflow のショートカットURL, IM-FileExchange のダウンロードURL、パスワードリマインダで複数のベースURLからのアクセスを実現したい場合、 メールテンプレートに以下のような形式で記述することで、任意のベースURL配下のURLにアクセスできます。
- %ご利用環境のベースURL固定文字% + [ショートカットURL置換文字列]
- 詳細は以下の要件情報を参照してください。
- ・IM-Workflow ベースURLを含まない置換文字列を提供します(2015 Spring~)
・IMBOX IMBoxの通知情報に含まれるURLにベースURLを含まれないようにします(2014 Summer~)
・IM-FileExchange ベースURLを含まないURLを文字列置換可能にする(2015 Summer~)
・パスワードリマインダ ベースURLを含まないURLを文字列置換可能にする(2015 Summer~)
- %ご利用環境のベースURL固定文字% + [ショートカットURL置換文字列]
Apache HTTP Server の設定
mod_headers モジュールを利用し、リクエスト情報を元に HTTP Header (x-com-base-url)に BaseURL を設定します。
前提条件
- 「静的ファイルの配置」がされていること。
- 「アクセスログの編集」の設定がされていること。
- 設定手順は セットアップガイド-Apache HTTP Server を参照してください。
- Apacheの稼働しているサーバへ2つのドメイン名からアクセスできるようにします。(app1.example.com および app2.example.com)
試験的に名前解決を行う場合はブラウザを利用するマシンのhostsファイルにドメイン名を記述します。
実際の運用ではDNSで名前解決できるようにしてください。- Windowsの場合は、C:\Windows\System32\drivers\etc\hosts に以下を追加します。
- ApacheサーバのIPアドレスが192.168.1.1の場合
192.168.1.1 app1.example.com 192.168.1.1 app2.example.com
モジュールの取得
以下の Apache モジュールを利用します。
- mod_proxy
- mod_rewrite
- mod_headers
手順
以降の手順では下記の環境を想定しています。
intra-mart Accel Platform のコンテキストパス | imart |
Apache のドキュメントルート | /usr/local/apache/htdocs |
静的ファイルの展開フォルダ | /usr/local/apache/htdocs/imart |
intra-mart Accel Platform の IP アドレス | 192.168.1.2 |
intra-mart Accel Platform のポート番号 | 8080 |
Apache の IP アドレス | 192.168.1.1 |
Apache のポート番号 | 80 |
- <%APACHE_HOME%/conf/httpd.conf> ファイルを開きます。
- Dynamic Shared Object (DSO) Support エリアに以下の設定を追加またはコメントアウトを外してください。
LoadModule proxy_module modules/mod_proxy.so LoadModule proxy_http_module modules/mod_proxy_http.so LoadModule rewrite_module modules/mod_rewrite.so LoadModule headers_module modules/mod_headers.so
- 以下のように RequestHeader の設定(22 および 23行目)を2行追加してください。
SetEnv proxy-nokeepalive 1 AllowEncodedSlashes On RewriteEngine On RewriteCond %{REQUEST_URI} !^/imart/reverse_proxy/ RewriteCond %{REQUEST_URI} ^/imart/(.*\.gif|.*\.GIF)$ [OR] RewriteCond %{REQUEST_URI} ^/imart/(.*\.png|.*\.PNG)$ [OR] RewriteCond %{REQUEST_URI} ^/imart/(.*\.jpg|.*\.JPG)$ [OR] RewriteCond %{REQUEST_URI} ^/imart/(.*\.jpeg|.*\.JPEG)$ [OR] RewriteCond %{REQUEST_URI} ^/imart/(.*\.css|.*\.CSS)$ [OR] RewriteCond %{REQUEST_URI} ^/imart/(.*\.js|.*\.JS)$ [OR] RewriteCond %{REQUEST_URI} ^/imart/(.*\.swf|.*\.SWF)$ [OR] RewriteCond %{REQUEST_URI} ^/imart/(.*\.ico|.*\.ICO)$ [OR] RewriteCond %{REQUEST_URI} ^/imart/(.*\.svg|.*\.SVG)$ [OR] RewriteCond %{REQUEST_URI} ^/imart/(.*\.json|.*\.JSON)$ [OR] RewriteCond %{REQUEST_URI} ^/imart/(.*\.jar|.*\.JAR)$ [OR] RewriteCond %{REQUEST_URI} ^/imart/(.*\.xml|.*\.XML)$ [OR] RewriteCond %{REQUEST_URI} ^/imart/(.*\.yaml|.*\.YAML)$ [OR] RewriteCond %{REQUEST_URI} ^/imart/(.*\.txt|.*\.TXT)$ [OR] RewriteCond %{REQUEST_URI} ^/imart/(.*\.html|.*\.HTML|.*\.htm|.*\.HTM)$ RewriteRule ^/imart/(.*)?$ /imart/$1 RequestHeader set x-com-base-url https://%{HTTP_HOST}s/imart env=https RequestHeader set x-com-base-url http://%{HTTP_HOST}s/imart env=!https RewriteCond %{HTTP:Connection} Upgrade [NC] RewriteCond %{HTTP:Upgrade} websocket [NC] RewriteRule ^/imart/(.*)?$ ws://192.168.1.2:8080/imart/$1 [P,L] ProxyPreserveHost On ProxyPass /imart/ http://192.168.1.2:8080/imart/ nocanon ProxyPassReverse /imart/ http://192.168.1.2:8080/imart/ nocanon ProxyTimeout 1200
- Apache を再起動してください。
BaseUrlProvider の実装
HTTP Header に応じて異なる BaseURL を返却する BaseUrlProvider を実装します。
- 以下の内容のファイルを WEB-INF/classes/com/example/HttpHeaderBaseUrlProvider.java として保存します。
-
package com.example; import javax.servlet.http.HttpServletRequest; import jp.co.intra_mart.common.annotation.Priority; import jp.co.intra_mart.foundation.platform.BaseUrlProvider; import java.util.Enumeration; // Priority を設定することで、実装クラスの呼び出し順を制御できます。ここでは、100 とします。 @Priority(value = 100) public class HttpHeaderBaseUrlProvider implements BaseUrlProvider { private static final String BASE_URL_HEADER_KEY = "x-com-base-url"; @Override public String getBaseUrl(final HttpServletRequest request) { if (request == null) { return null; } final String orgBaseUrl = request.getHeader(BASE_URL_HEADER_KEY); if (orgBaseUrl != null && orgBaseUrl.length() > 0) { return orgBaseUrl; } else { // null を返却することで、後続の BaseUrlProvider に処理を委ねることができます。 return null; } } }
- HTTP Header「x-com-base-url」の値を BaseURL として利用します。
「x-com-base-url」が存在しない場合は、後続の BaseUrlProvider に処理を委ねます。
-
- 以下の内容のファイルを WEB-INF/classes/META-INF/services/jp.co.intra_mart.foundation.platform.BaseUrlProvider として保存します。
-
com.example.HttpHeaderBaseUrlProvider
-
- intra-mart AccelPlatform を起動してください。
動作確認
以下を確認してください。
-
- http://app1.example.com/imart/homeにアクセス
- BaseURL が http://app1.example.com/imart/ になっていること
- http://app2.example.com/imart/homeにアクセス
- BaseURL が http://app2.example.com/imart/ になっていること
- http://app1.example.com/imart/homeにアクセス
応用
図のようにクライアントと WebServer の間に Load Balancer がある場合
WebServer で HTTP Header(x-com-base-url)を設定するのではなく、Load Balancer で作成した BaseURL を HTTP Header(x-com-base-url)に設定するようにしてください。
これは、クライアントが最初にアクセスするサーバが Load Balancer となるためです。