HttpURLConnection#getResponseCodeで-1が戻る
先日はHTTP_STATUS=302が戻るサーバへの対処とリダイレクト処理に言及したが、今日別なサーバに接続してみた所、今度は接続直後の処理が処理がおかしい。
今回の問題が再現するのはBASIC認証が必要なサイトへの接続だ。
URL url = new URL("http://hogehost/require/badicAuth"); URLConnection con = url.openConnection(); con.setDoInput(true); con.setDoOutput(true); con.setConnectTimeout(30000) ; conn.connect(); int http_status = conn.getResponseCode();
http_statusの戻りを判定してその後の処理(301, 401, etc)に移りたいのだが、実際にはhttp_statusの値が初期値の-1のままであり、更にはNullPointerExceptionがスローされしまう。
ならばとヘッダから同ステータスを取得しようと
int http_status = Integer.parseInt(httpcon.getHeaderField("StatusCode"));
これでも結果は同じ。
期待するHTTP_STATUSは当然ながら401なのだがどうしてこんなことになってしまうんだろう。
実装クラスである、org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnection.javaを調べてみたのだが、401(HTTP_UNAUTHORIZED)以降、内部disconnect()メソッドで接続を一端切っており、その後内部ストリームを閉じてクリアしてしまっているため、ストリームの取得に失敗しているらしい。
public int getResponseCode() throws IOException { // Response Code Sample : "HTTP/1.0 200 OK" // Call connect() first since getHeaderField() doesn't return exceptions connect(); doRequest();: : : void doRequestInternal() throws IOException { int redirect = 0; while (true) { : : // HTTP authorization failed ? if (responseCode == HTTP_UNAUTHORIZED) { // keep asking for username/password until authorized String challenge = resHeader.get("WWW-Authenticate"); //$NON-NLS-1$ if (challenge == null) { // KA018=Received authentication challenge is null throw new IOException(Msg.getString("KA018")); //$NON-NLS-1$ } // drop everything and reconnect, might not be required for // HTTP/1.1 endRequest(); ← HTTP_UNAUTHORIZED(401)だったら、 disconnect(); ← それまでのコネクションを切断してしまう : : private synchronized void disconnect(boolean closeSocket) { if (connection != null) { : : connection.closeSocketAndStreams(); } else { HttpConnectionManager.getDefault().returnConnectionToPool( connection); } connection = null; ← } } : : String readln() throws IOException { boolean lastCr = false; StringBuffer result = new StringBuffer(80); int c = is.read(); ← ぬるぽ : : }
どうやらバグのようだ。
HttpURLConnection.getResponseCode() returns -1 on second invocation - Stack Overflow
HttpURLConnection getResponseCode - Android Developers Google グループ
内部で使用されているのは知りつつも、依存してはいけないと避けていたのだが、やはりHttpClientを使えということなのかな。