androidでホスト名に_(アンダースコア)が入っていると通信に失敗する
タイトルの通りandroidでホスト名に_(アンダースコア)が入っていると通信に失敗する。
同じホストに対しiosで通信を試みたところ問題は発生しなかった。
通信失敗時のスタックトレース
E/AndroidRuntime(1278):Causedby: java.lang.NullPointerException
E/AndroidRuntime(1278):>---at libcore.net.http.HttpConnection$Address.hashCode(HttpConnection.java:343)
E/AndroidRuntime(1278):>---at java.util.HashMap.get(HashMap.java:298)
E/AndroidRuntime(1278):>---at libcore.net.http.HttpConnectionPool.get(HttpConnectionPool.java:67)
E/AndroidRuntime(1278):>---at libcore.net.http.HttpConnection.connect(HttpConnection.java:128)
E/AndroidRuntime(1278):>---at libcore.net.http.HttpEngine.openSocketConnection(HttpEngine.java:308)
E/AndroidRuntime(1278):>---at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:460)
E/AndroidRuntime(1278):>---at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:432)
E/AndroidRuntime(1278):>---at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:282)
E/AndroidRuntime(1278):>---at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:232)
E/AndroidRuntime(1278):>---at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:273)
E/AndroidRuntime(1278):>---at libcore.net.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:479)
E/AndroidRuntime(1278):>---at libcore.net.http.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:133)
コードから原因を追っていったところ、スタックトレースにも出ているとおり libcore.net.http.HttpConnection$Address.hashCode
メソッド内の uriHost.hashCode()
でNullPointerException
が発生していた。
uriHost
はjava.net.URI
クラスのgetHost
メソッドの結果が格納されている。 java.net.URI
クラスはRFC2396に準拠しており、ホスト名に使用する文字は以下のように定義されている。
RFC2396
3.2.2.Server-based NamingAuthority
hostport = host [":" port ]
host = hostname |IPv4address
hostname =*( domainlabel ".") toplabel ["."]
domainlabel = alphanum | alphanum *( alphanum |"-") alphanum
toplabel = alpha | alpha *( alphanum |"-") alphanum
上記のようにホスト名として定義されてる文字として_(アンダースコア)は定義されておらず、
ライブラリの実装によっては問題を引き起こす模様/(^o^)\。
今回の事象の場合、ホスト名に_(アンダースコア)が入っているとjava.net.URI.getHost()
の返り値がnull
になってしまう。
という予想が立ったので以下のテストコードで挙動を確認。
・テストコード
URLは仮のもの
package test;
import java.net.URI;
import java.net.URISyntaxException;
public class UriWithUnderScoreTest {
/**
* @param args
* @throws URISyntaxException
*/
public static void main(String[] args) throws URISyntaxException {
// TODO Auto-generated method stub
String uri_underscore ="http://api_dev.hogehoge.net/player/get";
System.out.println("uri="+ uri_underscore);
System.out.println("URI.getHost()="+new URI(uri_underscore).getHost());
String uri_hyphen ="http://api-dev.hogehoge/player/get";
System.out.println("uri="+ uri_hyphen);
System.out.println("URI.getHost()="+new URI(uri_hyphen).getHost());
}
}
・結果
uri=http://api_dev.hogehoge.net/player/get
URI.getHost()=null
uri=http://api-dev.hogehoge.net/player/get
URI.getHost()=api-dev.hogehoge.net
結果に出力されたとおり、ホスト名に_(アンダースコア)が入っているとnullが返り、
_(アンダースコア)を-(ハイフン)に置き換えたところ期待どおりの結果が返ってくる。