目次

ここは

よく使う Jakarta Apache Commonsのメモ

URL Encodingの問題

Commons-HttpClient? 3.0は URL Encodingに Commons-Codecを使っている。 具体的には諸々端折って書くと、以下の通り。
HttpMethodBaseのメソッド
public void setQueryString(NameValuePair [] params) {
	queryString = EncodingUtil.formUrlEncoding(params, "UTF-8");
}

以下、EncodingUtilのメソッド
public static String formUrlEncoding(NameValuePari [] nvp, String charset) {
	return doFormUrlEncoding(nvp, charset);
}
private static String doFormUrlEncode(NameValuePair [] nvp, String cs) {
	StringBuffer sb = new StringBuffer();
	for ( int i = 0; i < nvp.length; i++ ) {
		URLCodec codec = new URLCodec();
		NameValuePair n = nvp[i];
		if ( n.getName() != null ) {
			if ( i > 0 ) {
				sb.append("&");
			}
			sb.append(codec.encode(n.getName(), cs);
			sb.append("=");
		}
		if ( n.getValue() != null ) {
			sb.append(codec.encode(n.getValue(),cs);
		}
	}

	return sb.toString();
}
この Commons-Codecの encode()メソッドはRFC1738の 2.2節の最後の方で encodeしないでも使ってよい特殊文字 $-_.+!*'(),"に関しては encodeしない。
firefox等の一般的なweb browserではこれらの内、- があった場合、URL Encodeの 対象となっているが、HttpClient?では Commons-Codecが対象外としているみたいなので、 使うときに注意が必要である。

ツールを作っていた時に - が対象外になっていた事が問題だと思っていたら、/ と 間違えていた事が分かってしまい、、、^^;
「あんた、バカァ〜?」と聞こえてきそうである。。。

Commons-Codec-1.3の実装を見ると

encode対象外はURLCodecのprivate static final java.util.BitSet?変数WWW_FORM_URLに セットされている。対象外は[a-zA-Z0-0]と[-_.* ]。
どうにもならんので、起動時のSystem propertyを見て、- を外せるように commons-codecを変えてbuildし直した。下記は、Commons-Codec 1.3の org.apache.commons.codec.net.URLCodecクラスの変更した箇所だけの抜粋。
// special edition
private static final String MAGE_SPECIAL_KEY = "info.mage.commons.codec.special";
private static boolean isSpecialEdition = false;
// Static initializer for www_form_url
static {
	// special edition
	String specialKey = null;
	String default_specialKey = "_.* ";
	if ( System.getProperty(MAGE_SPECIAL_KEY) != null ) {
		isSpecialEdition = true;
		specialKey = System.getProperty(MAGE_SPECIAL_KEY);
		if ( specialKey.length() == 0 ) {
			specialKey = default_specialKey;
		}
	}
	
    // alpha characters
    for (int i = 'a'; i <= 'z'; i++) {
        WWW_FORM_URL.set(i);
    }
    for (int i = 'A'; i <= 'Z'; i++) {
        WWW_FORM_URL.set(i);
    }
    // numeric characters
    for (int i = '0'; i <= '9'; i++) {
        WWW_FORM_URL.set(i);
    }
    // special chars
    if ( !isSpecialEdition ) {
    	WWW_FORM_URL.set('-');
        WWW_FORM_URL.set('_');
        WWW_FORM_URL.set('.');
        WWW_FORM_URL.set('*');
        // blank to be replaced with +
        WWW_FORM_URL.set(' ');
    } else {
    	for ( int i = 0; i < specialKey.length(); i++ ) {
    		WWW_FORM_URL.set(specialKey.charAt(i));
    		
    	}
    }
}
と言うことで、起動時に -Dinfo.mage.commons.codec.specialを指定すれば、-だけ抜いた 形で動く。更に値をセットすると、1文字ずつ url encode対象外の文字になる。

上記の変更をしたのをここに 置いておきました。クラスファイルだけのzipです。まぁ、使えることもあろうかと言うことで。。。^^;

参考文献


Last-modified: 2006-03-29 11:10:58