HTTPServiceでRefererを変更

Posted: 7月 28th, 2009 | Author: admin | Filed under: 技術メモ | No Comments »

Apacheのログを見てると「HTTPService リファラ」という検索ワードで来てる人がいた。何故この検索ワードでこのBlogが引っ掛かるのかはわからないが、そういえばHTTPServiceクラスでHTTPヘッダの設定をしたことが無いので調べてみた。

まず普通にHTTPServiceクラスのheadersプロパティにRefererをセットしてみる。

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="{doit()}">
    <mx:Script>
        <![CDATA[
            import mx.rpc.http.HTTPService;
            import mx.rpc.events.ResultEvent;
            import mx.rpc.events.FaultEvent;
            import mx.rpc.AsyncToken;
            import mx.rpc.AsyncResponder;
            import mx.controls.Alert;
 
            private function doit():void{
                var httpService:HTTPService = new HTTPService();
                httpService.url = "http://darelog.konoha.jp/";
                httpService.headers["Referer"] = "http://dummy.darelog.jp/";
                var asyncToken:AsyncToken = httpService.send();
                asyncToken.addResponder(new AsyncResponder(successHandler, errorHandler));
            }
 
            private function successHandler(e:ResultEvent, obj:Object=null):void{
                Alert.show("ok", "ok", Alert.OK);
            }
 
            private function errorHandler(e:FaultEvent, obj:Object=null):void{
                Alert.show("ng", "ng", Alert.OK);
            }
 
 
        ]]>
    </mx:Script>
</mx:Application>

コンパイルは問題なく通るが、実行時にエラー発生。
デバッグしてみると

Error #2096 HTTP リクエストヘッダ Referer を ActionScript から設定することはできません。

とのエラー。
HTTPServiceクラスの中で潰してるのあれば、該当箇所をコメントアウトすればいけるかな、と思いHTTPService.asの中を覗いていくが、それらしい部分は無し。基底クラスのAbstractInvokerの中身も簡単に覗いてみたが、こんな場所で上位レイヤのエラー処理をするわけはないわなと。
そもそも、こんなところで潰してるならコンパイル時にエラーを吐いてくれると思うのでVMの側でエラーを出してるのかも。
URLRequestHeader ActionScript 3.0 – 言語およびコンポーネントリファレンス -
HTTPServiceクラスでは内部で上記URLRequestHeaderクラスを使用しているが、そのクラスの解説文章にも

Flash Player およびアプリケーションセキュリティサンドボックス外の Adobe AIR コンテンツでは、次のリクエストヘッダを使用できません。これらの制限対象の語では大文字と小文字は区別されません(例えば、Get、get、GET はすべて使用できません)。また、アンダースコア文字が使用されている場合は、ハイフンのある語が該当します(例えば、Content-Length と Content_Length は共に禁止されています)。

Accept-Charset、Accept-Encoding、Accept-Ranges、Age、Allow、Allowed、Authorization、Charge-To、Connect、Connection、Content-Length、Content-Location、Content-Range、Cookie、Date、Delete、ETag、Expect、Get、Head、Host、Keep-Alive、Last-Modified、Location、Max-Forwards、Options、Post、Proxy-Authenticate、Proxy-Authorization、Proxy-Connection、Public、Put、Range、Referer、Request-Range、Retry-After、Server、TE、Trace、Trailer、Transfer-Encoding、Upgrade、URI、User-Agent、Vary、Via、Warning、WWW-Authenticate、x-flash-version

とあるので、FlashPlayer側の中身に手を出せない以上はお手上げか~。

と思っていろいろ探してみると
as3httpclientlib
というのがあった。flash.net.SocketでHTTPクライアントを実装したものらしい。
これを使ってみると

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="{doit()}">
    <mx:Script>
        <![CDATA[
            import org.httpclient.*;
            import org.httpclient.events.*;
            import org.httpclient.http.*;
 
            import com.adobe.net.URI;
 
            import mx.controls.Alert;
 
            private function doit():void{
                var client:HttpClient = new HttpClient();
                var uri:URI = new URI("http://darelog.konoha.jp/");
                var request:HttpRequest = new Get();
                request.addHeader("Referer", "http://dummy.konoha.jp/");
 
                client.listener.onData = this.dataHandler;
                client.request(uri, request);
            }
 
            private function dataHandler(e:HttpDataEvent):void{
                var string:String = e.readUTFBytes();
                Alert.show(string, "result", Alert.OK);
            }
        ]]>
    </mx:Script>
</mx:Application>

でばっちりOK。
Referer以外でHTTPRequestHeaderで使用できないものも(上記参照)セットできるので便利。

使用する場合はas3corelibもlibに追加しておく。(URIクラスを使用するため)
また、as3cryptoもlibに追加しておかないとランタイムエラーが発生する。(org.httpclient.HttpSocket内でTLS通信かどうかを判別するために使用。そのため、プログラム内でTLS通信を行っていなくても必要となる。)
内部ではSocketクラスを使用しているので、Socketクラスのセキュリティ制限を考慮する必要有。

* 呼び出し元 SWF ファイルが ローカルファイルシステムのサンドボックスにあり、ターゲットリソースがネットワーク上のサンドボックスにある場合、データをロードできません。
* 呼び出し元 SWF ファイルがネットワーク上のサンドボックスにあり、ターゲットリソースがローカルにある場合、データをロードできません。
* 呼び出し側の SWF ファイルとアクセスされるネットワークリソースは、同じドメインに置かれている必要があります。たとえば adobe.com に置かれている SWF ファイルは、adobe.com 上のサーバーデーモンにしか接続できません。
* Web サイトでクロスドメインポリシーファイルを使用して、リソースへのクロスドメインアクセスを許可できます。



Leave a Reply