Enctype/ application/x-www-form-urlencoded
HTMLのフォームタグと違って、Ajaxの場合、GET/POSTで送信しても、 Enctypeを自動で設定してくれるわけでは在りません(Safariは設定されます)。でも、それをほったらかしにするのは、HTML 4.xあたりに怒られるん?というあたりが気になったので、少しだけ調べてみました。
とりあえず、先にtest3.htmまで行って出した結論?を書いておきます。

結論は、Ajax通信時には、oj.setRequestHeader('Content-Type','application/x-www-form-urlencoded; charset=UTF-8')とかを明示的にセットしないとRFCやW3CのHTML4x違反ぽいですし、そもそもサーバーへ届かないブラウザがあります。

サーバー側からの返信時には、データUTF-8(BOM付き)にできるなら、BOM付きという部分でユニコード判定ができるようですので、サーバー/クライアントともにUTF-8にそろえられる環境ならいける可能性があります(日本の多くのサーバー環境ではまだ難しいかも)。あるいは、サーバー送出時にもUTF-8化したあとにURIエンコードなどして送出し、受信時に、decodeURIComponent(oj.responseText)すると、必ずUTF-8としてJavaScriptが解釈してくれますので、サーバーとクライアント側HTMLの文字コードが何であっても文字化けしなくなります。

もちろん、URIエンコードではデータ量が増えてしまいますので、 この際、返信時は、Safari(とKHTML)だけ行うというのでもOK。あるいは、圧縮送信するとか、、、。また、setRequestHeaderはSafariは無くても良い。あと、注意したいのは、Opera8.01以前では、setRequestHeaderがエラーになるので分岐が必要。


関連
  • test2.htm :: test1.htmの調査でいくつか問題のあったAjax通信について、送出時にJavaScriptのencodeURIComponent()でURIエンコードしてみてどうなるかを調べました。
  • test3.htm :: 送出は、test2.htmのままで、サーバー側からの返信時にURIエンコードして送出してみます

    参考
    PHPとJavaScriptのURIエンコードを比較

    HTML 4.0( 日本語訳 )
    17.13.3 フォーム・データの処理
    HTML 4.01( 日本語訳 )
    17.13.3 フォーム・データの処理

    enctype = content-type [CI] この属性は、サーバーにフォームを転送するために使われる content typeを特定します( methodの値が"post"の場合)。この属性の初期値は、 "application/x-www-form-urlencoded"です。 "multipart/form-data"値は、 type="file"のある INPUT要素と組で使わなければなりません。

    methodが"get"で、 actionがHTTP URIである場合は actionの値を取り、それに`?'を付け、次いで "application/x-www-form-urlencoded" content typeを使ってコード化された フォーム・データ・セットを追加します。そしてリンクをURIにわたします。この過程でフォーム・データはASCIIコードに限定されます。 methodが"post"で actionがHTTP URIの場合は、 action属性を使ってHTTP "post"処理と enctype属性によって特定された 内容タイプに従って作成されたメッセージを伝えます。


    [ NG ]と書いてあっても、該当ケースの場合は単にうまくいかないというだけのことであって、ブラウザに責任があるというような話ではありません。

    POSTでフォーム送信、enctype属性を省略
    送信ojmethodform要素のenctype属性setRequestHeaderでのContent-Type指定
    FORM POST 属性省略 なし
    リクエストヘッダに自動セットされ(Content-Type: application/x-www-form-urlencoded)、データはサーバーへ届き、文字化けもしません。WinIEの送出パケットを見たら、URIエンコードされていました。
    <form name    = "test1"
          action  = "http://jsgt.org/ajax/ref/test/enctype/header.php"
          method  = "post">
      <input type  = "text" 
             name  = "test"
             value = "------テスト------">
      <input type  = "submit"
             value = "送信">
    </form>
    

    POSTでフォーム送信、enctype = "application/x-www-form-urlencoded"を明示指定
    送信ojmethodform要素のenctype属性setRequestHeaderでのContent-Type指定
    FORM POST application/x-www-form-urlencoded なし
    リクエストヘッダにセットされ、データはサーバーへ届き、文字化けもしません。WinIEの送出パケットを見たら、URIエンコードされていました。
    <form enctype = "application/x-www-form-urlencoded"
          name    = "test2"
          action  = "http://jsgt.org/ajax/ref/test/enctype/header.php"
          method  = "post">
      <input type  = "text" 
             name  = "test"
             value = "------テスト------">
      <input type  = "submit"
             value = "送信">
    </form>
    

    GETでフォーム送信、enctype属性を省略
    送信ojmethodform要素のenctype属性setRequestHeaderでのContent-Type指定
    FORM GET 属性省略 なし
    リクエストヘッダにセットされませんが、データはサーバーへは届き、文字化けもしません。WinIEの送出パケットを見たら、URIエンコードされていました。
    <form name    = "test3"
          action  = "http://jsgt.org/ajax/ref/test/enctype/header.php"
          method  = "get">
      <input type  = "text" 
             name  = "test"
             value = "------テスト------">
      <input type  = "submit"
             value = "送信">
    </form>
    

    ここからAjax送信
    <script>
    
    //暫定版Ajax用ライブラリのミニ版
    //http://jsgt.org/mt/archives/01/000409.html
    
    	////
    	// XMLHttpRequestオブジェクト生成
    	//
    	// @sample           oj = createHttpRequest()
    	// @return           XMLHttpRequestオブジェクト
    	//
    	function createHttpRequest()
    	{
    		if(window.ActiveXObject){
    			 //Win e4,e5,e6用
    			try {
    				return new ActiveXObject("Msxml2.XMLHTTP") ;
    			} catch (e) {
    				try {
    					return new ActiveXObject("Microsoft.XMLHTTP") ;
    				} catch (e2) {
    					return null ;
    	 			}
    	 		}
    		} else if(window.XMLHttpRequest){
    			 //Win Mac Linux m1,f1,o8 Mac s1 Linux k3用
    			return new XMLHttpRequest() ;
    		} else {
    			return null ;
    		}
    	}
    
    	function sendRequest(data,method,url , encSwt)
    	{
    		//XMLHttpRequestオブジェクト生成
    		var oj = createHttpRequest();
    		
    		oj.onreadystatechange =function () 
    		{
    			if ( oj.readyState == 4 ){
    				alert(oj.responseText);
    			}
    		}
    
    		//URI
    		if(method.toUpperCase() == 'GET') {
    			url += "?"+data
    		}
    		
    		//open メソッド
    		oj.open(method,url);
    
    		//ヘッダapplication/x-www-form-urlencodedセット
    		if(encSwt == 1)setEnc(oj)
    
    		//send メソッド
    		oj.send(data);
    	}
    
    
    	function setEnc(oj){
    	
    		//ヘッダapplication/x-www-form-urlencodedセット
    		// @see  http://www.asahi-net.or.jp/~sd5a-ucd/rec-html401j/interact/forms.html#h-17.13.3
    		// @see  #h-17.3
    		//   ( enctype のデフォルト値は "application/x-www-form-urlencoded")
    		//   h-17.3により、POST/GET問わず設定
    		//   POSTで"multipart/form-data"を指定する必要がある場合はカスタマイズしてください。
    		//
    		//  このメソッドがWin Opera8.0でエラーになったので分岐(8.01はOK)
    		var contentTypeUrlenc = 'application/x-www-form-urlencoded; charset=UTF-8';
    		if(!window.opera){
    			oj.setRequestHeader('Content-Type',contentTypeUrlenc);
    		} else {
    			if((typeof oj.setRequestHeader) == 'function')
    				oj.setRequestHeader('Content-Type',contentTypeUrlenc);
    		}	
    		return oj
    	}
    
    </script>
    
    
    GETでAjax送信、setRequestHeader()でのenctype属性指定なし
    送信ojmethodform要素のenctype属性setRequestHeaderでのContent-Type指定
    XMLHttpRequest GET 属性省略 なし
    WinIE、Opera8.02、Firefox1.02は、リクエストヘッダにセットされませんが、データはサーバーへ届き文字化けしません。
    [ NG ]Mac Safari1.25は、リクエストヘッダにセットされ、データはサーバーへ届きますが、文字化けします。
    WinIEの送出パケットを見たら、URIエンコードはされていませんでした。
    <form name    = "test4">
      <input type  = "text" 
             name  = "test"
             value = "------テスト------">
      <input type  = "button"
             onclick ="
               sendRequest("&test="+this.form.test.value,
                           'get',
                           'http://jsgt.org/ajax/ref/test/enctype/header.php')"
             value = "送信">
    </form>
    

    POSTでAjax送信、setRequestHeader()でのenctype属性指定なし
    送信ojmethodform要素のenctype属性setRequestHeaderでのContent-Type指定
    XMLHttpRequest POST 属性省略 なし
    [ NG ]WinIE、Opera8.02、Firefox1.02は、リクエストヘッダにセットされず、データはサーバーへ届いていません。
    [ NG ]Mac Safari1.25は、リクエストヘッダにセットされ、データはサーバーへ届きますが、文字化けします。
    WinIEの送出パケットを見たら、URIエンコードはされていませんでした(データがサーバーへ届いていないように見えたのは、サーバーで処理できていないだけの可能性大)。
    <form name    = "test5">
      <input type  = "text" 
             name  = "test"
             value = "------テスト------">
      <input type  = "button"
             onclick ="
               sendRequest('&test='+this.form.test.value,
                           'post',
                           'http://jsgt.org/ajax/ref/test/enctype/header.php')"
             value = "送信">
    </form>
    

    POSTでAjax送信、setRequestHeader()でのenctype属性指定なし。フォームのenctype属性で指定してみる。
    送信ojmethodform要素のenctype属性setRequestHeaderでのContent-Type指定
    XMLHttpRequest POST application/x-www-form-urlencoded なし
    [ NG ]WinIE、Opera8.02、Firefox1.02は、リクエストヘッダにセットされず、データはサーバーへ届いていません。
    [ NG ]Mac Safari1.25は、リクエストヘッダにセットされ、データはサーバーへ届きますが、文字化けします。
    WinIEの送出パケットを見たら、URIエンコードはされていませんでした(データがサーバーへ届いていないように見えたのは、サーバーで処理できていないだけの可能性大)。
    <formform  enctype = "application/x-www-form-urlencoded"
           name    = "test6">
      <input type  = "text" 
             name  = "test"
             value = "------テスト------">
      <input type  = "button"
             onclick ="
               sendRequest('&test='+this.form.test.value,
                           'post',
                           'http://jsgt.org/ajax/ref/test/enctype/header.php')"
             value = "送信">
    </form>
    

    POSTでAjax送信、setRequestHeader()でのenctype属性指定あり
    送信ojmethodform要素のenctype属性setRequestHeaderでのContent-Type指定
    XMLHttpRequest POST 属性省略 application/x-www-form-urlencoded
    WinIE、Opera8.02、Firefox1.02は、リクエストヘッダにセットされ、データはサーバーへ届き文字化けしません。
    [ NG ]Mac Safari1.25は、リクエストヘッダにセットされ、データはサーバーへ届きますが、文字化けします。
    WinIEの送出パケットを見たら、URIエンコードはされていませんでした。
    <form name    = "test7">
      <input type  = "text" 
             name  = "test"
             value = "------テスト------">
      <input type  = "button"
             onclick ="
               sendRequest('&test='+this.form.test.value,
                           'post',
                           'http://jsgt.org/ajax/ref/test/enctype/header.php',1)"
             value = "送信">
    </form>
    

    
    	

  • 【作業用掲示板】