2012年09月13日
クロスドメイン制約を回避するProxyをMTMLで作る
JavaScriptやActionScriptで外部のXMLを読み込む場合などにクロスドメインの制約で読み込めないケースがあります。また、HTTPSのページからHTTPで提供されているAPIへリクエストを送信すると、一部のブラウザでセキュリティの警告が表示される問題が発生します。
これを回避する方法としてPHP等でProxyを作成し、自ドメインのサーバーに設置する方法があります。このProxyをMTとDynamicMTMLのタグだけで実現する方法をご紹介します。今回は以下のAPIを例にします。
以下のようなリクエストを送信すると、JSON形式でレスポンスが返ってきます。
http://api.postalcode.jp/v1/zipsearch?zipcode=541-0047
{ "zipcode": {"a1" :{ "zipcode":"5410047","prefecture":"大阪府","city":"大阪市中央区","town":"淡路町","prefecture_yomi":"オオサカフ","city_yomi":"オオサカシチュウオウク","town_yomi":"アワジマチ" }
}, "office":{} }
テンプレートは以下です。拡張子を .js、テンプレートの公開オプションは「ダイナミック」とします(拡張子.js をDynamicMTML対象とするには負荷が大きいため、ダイナミックパブリッシングを利用します。)。
<mt:setvarblock name="api_url">
http://api.postalcode.jp/v1/zipsearch?zipcode=<mt:query key="zipcode">
</mt:setvarblock>
<mt:filegetcontents url="$api_url">
見やすくするために改行を入れています。実際は一行で記述してください。 最初の mt:setvarblock ブロックタグで API のURLにqueryパラメタを追加して変数 api_url にセットします。mt:filegetcontents タグの url モディファイアに $api_url を渡してそのまま API へ投げたリクエストへのレスポンスをブラウザに返します。
このテンプレートを自社ドメイン直下に出力されるインデックス・テンプレート(出力ファイル名 - 例:zipcode.html)として登録します。下記のURLで同様のレスポンスが得られるようになります。
https://自社ドメインのURL/zipcode.html?=541-0047
尚、拡張子を .js とした際、Content-Typeレスポンスヘッダは text/javascript になります。JSON を返す場合、Content-Typeレスポンスヘッダは以下の形が望ましいため、Content-Typeレスポンスヘッダを変更するために、DynamicMTMLのプラグインを作成することができます。
Content-Type: application/json; charset=UTF-8
このプラグインを使うことで、DynamicMTML処理が使えるようになります。スタティックファイルを吐き出すことで、負荷的な面でも若干有利になります。
<MTDynamicMTML>
<mt:setvarblock name="api_url">
http://api.postalcode.jp/v1/zipsearch?zipcode=<mt:query key="zipcode">
</mt:setvarblock>
<mt:filegetcontents url="$api_url">
</MTDynamicMTML>
見やすくするために改行を入れています。実際は一行で記述してください。 DynamicMTMLを通すために、拡張子を .html とし、(この例では postal_code_api.html )テンプレートの公開オプションを「スタティック(規定)」とします。
- plugins/SetContentType2json/php/config.php
<?php
class SetContentType2json extends MTPlugin {
var $registry = array(
'name' => 'SetContentType2json',
'callbacks' => array(
'post_init' => 'post_init'
),
);
function post_init ( $mt, $ctx, &$args ) {
$request = $args[ 'request' ];
$app = $ctx->stash( 'bootstrapper' );
if ( preg_match( "/\/postal_code_api\.html$/" , $request ) ) {
$app->stash( 'contenttype', 'application/json; charset=UTF-8' );
}
}
}
?>
コメントを投稿する