HTTP 404 等を受け取ろうとする処理でのHttpURLConnectionの使い方、
IOException でcatchして getErrorStream() で読まないとサーバが投げるメッセージを受け取れないのか~。
続きを読む... に、Httpクライアントのソースを載せることにした。。。。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
/**
* HTTP通信ユーティリティ.
* <pre>
* 指定URLへの HTTP送信または、HTTP(BASIC認証)送信を行う。
* </pre>
*/
public final class HttpUtilz{
/** HTTPヘッダ属性名 "Content-Type" */
public final static String KEY_CONTENT_TYPE = "Content-Type"; // text/xml
/** HTTPヘッダ属性名 "Content-Type" */
public final static String KEY_CONNECTION = "Connection"; // close
/** HTTPメソッド名 POST*/
public final static String POST = "POST";
/** HTTPメソッド名 GET*/
public final static String GET = "GET";
private HttpUtilz(){}
/**
* HTTP送信
* @param url URL
* @param headerMap 指定するHTTPヘッダをMap<String,String>で指定する.<br>
* HttpURLConnection#setRequestProperty(String,String)実行対象のMapである
* @param method リクエストメソッド GET or POST
* @param str 送信データ
* @param timeout 接続タイムアウト時間(ミリ秒)
* @param encode エンコード
* @return 応答レスポンス HttpUtilzResponseを参照してください
* @throws Exception
*/
public static HttpUtilzResponse send(URL url,Map<String,String> headerMap, String method
,String str,int timeout,String encode) throws Exception {
HttpURLConnection uc = null;
OutputStreamWriter osw = null;
HttpUtilzResponse res = new HttpUtilzResponse();
try{
// HttpURLConnectionオブジェクト取得
uc = (HttpURLConnection)url.openConnection();
/** HTTPリクエストヘッダの設定 */
uc.setDoOutput(true); // こちらからのデータ送信を可能とする
uc.setReadTimeout(timeout); // 読み取りタイムアウト値をミリ秒単位で設定(0は無限)
uc.setRequestMethod(method); // URL 要求のメソッドを設定
SimpleDateFormat sdf = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss",Locale.US);
uc.setRequestProperty("Date"," "+sdf.format(new Date()) + " GMT");
if(StringUtils.equals(POST, method)) {
uc.setRequestProperty("Content-Length",Integer.toString(str.getBytes(encode).length));
}
for(Iterator<String> it=headerMap.keySet().iterator();it.hasNext();){
String key = it.next();
uc.setRequestProperty(key,headerMap.get(key));
}
//コネクション確立
uc.connect();
/** アウトプットストリームにパラメータ出力 */
if(StringUtils.equals(POST, method)) {
osw = new OutputStreamWriter(uc.getOutputStream(), encode);
osw.write(str);
osw.flush();
}
/* 戻り値取得 */
res.setResponseCode(uc.getResponseCode());
res.setResponseMessage(uc.getResponseMessage());
BufferedReader in = new BufferedReader(new InputStreamReader(uc.getInputStream(),encode));
StringBuffer out = new StringBuffer();
try{
try{
char buf = new char[1024];
int n;
while((n = in.read(buf)) >= 0){
out.append(buf, 0, n);
}
res.setMessage(out.toString());
}finally{
in.close();
}
}catch(IOException e){
throw new RuntimeException(e);
}
res.setMessage(out.toString());
return res;
}catch(IOException e){
res.setResponseMessage(e.getMessage());
if (uc != null){
InputStream error_in = uc.getErrorStream();
if (error_in != null){
BufferedReader in_e = new BufferedReader(new InputStreamReader(error_in,encode));
StringBuffer out_e = new StringBuffer();
char buf = new char[1024];
int n;
try{
while*1 >= 0){
out_e.append(buf, 0, n);
}
}finally{
in_e.close();
}
res.setMessage(in_e.toString());
}
}
return res;
}catch(Exception e){
throw e;
}finally{
if (osw != null){ osw.close(); }
if (uc != null){ uc.disconnect(); }
}
}
/**
* HTTP送信(HTTPヘッダデフォルト)
* <pre>
* HTTPヘッダデフォルトは、以下
* Content-Type : text/xml
* Connection : close
* </pre>
* @param url URL
* @param str 送信データ
* @param timeout 接続タイムアウト時間(ミリ秒)
* @return 応答レスポンス HttpUtilzResponseを参照してください
* @throws Exception
*/
public static HttpUtilzResponse send(URL url,String str,int timeout) throws Exception{
Map<String,String> map = new HashMap<String,String>();
map.put(KEY_CONTENT_TYPE,"text/xml");
map.put(KEY_CONNECTION,"close");
return send(url,map,POST,str,timeout,"UTF-8");
}
/**
* HTTP送信(デフォルト).
* <br> デフォルトでは、接続タイムアウト時間は、30秒で、HTTPヘッダデフォルトである
* @param url URL
* @param str 送信データ
* @return 応答レスポンス HttpUtilzResponseを参照してください
* @throws Exception
*/
public static HttpUtilzResponse send(URL url,String str) throws Exception{
return send(url,str,30000);
}
/**
* HTTP送信 BASIC認証
* @param url URL
* @param headerMap 指定するHTTPヘッダをMap<String,String>で指定する.<br>
* HttpURLConnection#setRequestProperty(String,String)実行対象のMapである
* @param user ユーザID
* @param passwd パスワード
* @param method メソッド名
* @param str 送信データ
* @param timeout 接続タイムアウト時間(ミリ秒)
* @param encode エンコード
* @return 応答レスポンス HttpUtilzResponseを参照してください
* @throws Exception
*/
public static HttpUtilzResponse send(URL url,Map<String,String> headerMap,String user,String passwd
,String method,String str,int timeout,String encode) throws Exception{
// 認証用パラメータを作成する。(認証ID,パスワード)
String userpasswd = Base64Utilz.base64Encode(user+":"+passwd);
HttpURLConnection uc = null;
OutputStreamWriter osw = null;
InputStreamReader reader = null;
HttpUtilzResponse res = new HttpUtilzResponse();
try{
// HttpURLConnectionオブジェクト取得
uc = (HttpURLConnection)url.openConnection();
/** HTTPリクエストヘッダの設定 */
uc.setDoOutput(true); // こちらからのデータ送信を可能とする
uc.setReadTimeout(timeout); // 読み取りタイムアウト値をミリ秒単位で設定(0は無限)
uc.setRequestMethod(method); // URL 要求のメソッドを設定
SimpleDateFormat sdf = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss",Locale.US);
uc.setRequestProperty("Date"," "+sdf.format(new Date()) + " GMT");
if(StringUtils.equals(POST, method)) {
// Content-LengthはPOSTの場合だけ
uc.setRequestProperty("Content-Length",Integer.toString(str.getBytes(encode).length));
}
uc.setRequestProperty("Authorization"," Basic "+userpasswd);
for(Iterator<String> it=headerMap.keySet().iterator();it.hasNext();){
String key = it.next();
uc.setRequestProperty(key,headerMap.get(key));
}
//コネクション確立
uc.connect();
/** アウトプットストリームにパラメータ出力 */
if(StringUtils.equals(POST, method)) {
// POSTの場合だけ
osw = new OutputStreamWriter(uc.getOutputStream(), encode);
osw.write(str);
osw.flush();
}
/** 戻り値取得 */
res.setResponseCode(uc.getResponseCode());
res.setResponseMessage(uc.getResponseMessage());
reader = new InputStreamReader(uc.getInputStream(), encode);
BufferedReader in = new BufferedReader(new InputStreamReader(uc.getInputStream(),encode));
StringBuffer out = new StringBuffer();
try{
try{
char buf = new char[1024];
int n;
while((n = in.read(buf)) >= 0){
out.append(buf, 0, n);
}
}finally{
in.close();
}
}catch(IOException e){
throw new RuntimeException(e);
}
res.setMessage(out.toString());
return res;
}catch(IOException e){
res.setResponseMessage(e.getMessage());
if (uc != null){
InputStream error_in = uc.getErrorStream();
if (error_in != null){
BufferedReader in_e = new BufferedReader(new InputStreamReader(error_in,encode));
StringBuffer out_e = new StringBuffer();
char buf = new char[1024];
int n;
try{
while*2 >= 0){
out_e.append(buf, 0, n);
}
}finally{
in_e.close();
}
res.setMessage(in_e.toString());
}
}
return res;
}catch(Exception e){
throw e;
}finally{
if (osw != null){osw.close();}
if (reader != null){reader.close();}
if (uc != null){uc.disconnect();}
}
}
/**
* HTTP送信 BASIC認証(HTTPヘッダデフォルト).
* <pre>
* HTTPヘッダデフォルトは、以下
* Content-Type : text/xml
* Connection : close
* </pre>
* @param url URL
* @param user ユーザID
* @param passwd パスワード
* @param str 送信データ
* @param timeout 接続タイムアウト時間(ミリ秒)
* @return 応答レスポンス HttpUtilzResponseを参照してください
* @throws Exception
*/
public static HttpUtilzResponse send(URL url,String user,String passwd,String str,int timeout) throws Exception{
Map<String,String> map = new HashMap<String,String>();
map.put(KEY_CONTENT_TYPE,"text/xml");
map.put(KEY_CONNECTION,"close");
return send(url,map,user,passwd,str,POST,timeout,"UTF-8");
}
/**
* HTTP送信 BASIC認証(デフォルト).
* <br> デフォルトでは、接続タイムアウト時間は、30秒で、HTTPヘッダデフォルトである
* @param url URL
* @param user ユーザID
* @param passwd パスワード
* @param str 送信データ
* @return 応答レスポンス HttpUtilzResponseを参照してください
* @throws Exception
*/
public static HttpUtilzResponse send(URL url,String user,String passwd,String str) throws Exception{
return send(url,user,passwd,str,30000);
}
/**
* HTTP送信 BASIC認証(メソッド指定).
* <br> デフォルトでは、接続タイムアウト時間は、30秒で、HTTPヘッダデフォルトである
* @param url URL
* @param user ユーザID
* @param passwd パスワード
* @param method メソッド GET or POST
* @param str 送信データ
* @return 応答レスポンス HttpUtilzResponseを参照してください
* @throws Exception
*/
public static HttpUtilzResponse send(URL url,String user,String passwd, String method, String str) throws Exception{
Map<String,String> map = new HashMap<String,String>();
map.put(KEY_CONTENT_TYPE, "text/plain");
map.put(KEY_CONNECTION, "close");
return send(url, map, user, passwd, str, method, 30000, "UTF-8");
}
}
=========
import java.io.Serializable;
public final class HttpUtilzResponse implements Serializable{
private static final long serialVersionUID = 1L;
/** HTTP応答コード */
public int responseCode;
/** HTTP応答コードメッセージ */
public String responseMessage;
/** コンテンツメッセージ */
public String message;
/** デフォルトコンストラクタ */
public HttpUtilzResponse(){}
public HttpUtilzResponse(int responseCode,String responseMessage,String message){
this.responseCode = responseCode;
this.responseMessage = responseMessage;
this.message = message;
}
/**
* HTTP応答コード取得
* @return HTTP応答コード
*/
public int getResponseCode() {
return this.responseCode;
}
/**
* HTTP応答コードset
* @param responseCode HTTP応答コード
*/
public void setResponseCode(int responseCode) {
this.responseCode = responseCode;
}
/**
* HTTP応答コードメッセージ取得
* @return HTTP応答コードメッセージ
*/
public String getResponseMessage() {
return this.responseMessage;
}
/**
* HTTP応答コードメッセージset
* @param responseMessage HTTP応答コードメッセージ
*/
public void setResponseMessage(String responseMessage) {
this.responseMessage = responseMessage;
}
/**
* コンテンツメッセージ取得
* @return コンテンツメッセージ
*/
public String getMessage() {
return this.message;
}
/**
* コンテンツメッセージset
* @param message コンテンツメッセージ
*/
public void setMessage(String message) {
this.message = message;
}
}
=========
/**
* BASE64変換ユーティリティ.
*/
public final class Base64Utilz{
private Base64Utilz(){}
/**
* BASE64エンコード処理
* @param value 変換対象
* @return String 変換結果
*/
public static String base64Encode(String value){
return base64Encode(value.getBytes());
}
/**
* BASE64エンコード処理
* @param byteList 変換対象
* @return String 変換結果
*/
public static String base64Encode(byte byteList){
StringBuffer encoded = new StringBuffer();
for(int i=0; i < byteList.length;i+= 3){
encoded.append(base64EncodeBlock(byteList, i));
}
return encoded.toString();
}
/**
* BASE64変換処理
* @param byteList 変換対象
* @param iOffset 変換対象
* @return char 変換結果
*/
private static char base64EncodeBlock(byte byteList,int iOffset){
int block = 0;
int slack = byteList.length - iOffset - 1;
int end = (slack >= 2)? 2 : slack;
for(int i=0;i <= end;i++){
byte b = byteList[iOffset + i];
int neuter = (b < 0)? b + 256 : b;
block += neuter << (8 * (2 - i));
}
char base64 = new char[4];
for(int i=0;i < 4;i++){
int sixBit = (block >>> (6 * (3 - i))) & 0x3f;
base64[i] = base64EncodeGetChar(sixBit);
}
if (slack < 1) base64[2] = '=';
if (slack < 2) base64[3] = '=';
return base64;
}
/**
* BASE64変換処理
* 概要:指定された6ビットをBASE64形式でエンコードし、その文字を返す。
* @param iSixBit 6bit
* @return char 変換結果
*/
private static char base64EncodeGetChar(int iSixBit) {
if (iSixBit >= 0 && iSixBit <= 25) return (char)('A' + iSixBit);
if (iSixBit >= 26 && iSixBit <= 51) return (char)('a' + (iSixBit - 26));
if (iSixBit >= 52 && iSixBit <= 61) return (char)('0' + (iSixBit - 52));
if (iSixBit == 62) return '+';
if (iSixBit == 63) return '/';
return '?';
}
/**
* BASE64デコード処理
* 概要 :指定された文字列を、BASE64形式でデコードし、そのバイト列を返す
* @param base64 BASE64形式の文字列.
* @return デコード後のバイト列.
*/
public static byte base64Decode(String base64) {
if (base64==null || base64.length()==0 || base64.length()%4!=0) {
return new byte[0];
}
int pad = 0;
for(int i=base64.length() - 1; base64.charAt(i) == '='; i--)
pad++;
int length = base64.length() * 6 / 8 - pad;
byte raw = new byte[length];
int rawIndex = 0;
for(int i=0; i < base64.length();i += 4){
int block = (base64DecodeGetValue(base64.charAt(i)) << 18)
+ (base64DecodeGetValue(base64.charAt(i + 1)) << 12)
+ (base64DecodeGetValue(base64.charAt(i + 2)) << 6)
+ (base64DecodeGetValue(base64.charAt(i + 3)));
for(int j=0; j < 3 && rawIndex + j < raw.length;j++)
raw[rawIndex + j] = (byte)((block >> (8 * (2 - j))) & 0xff);
rawIndex += 3;
}
return raw;
}
/**
* BASE64デコード処理(6ビット)
* 概要 :BASE64形式の文字からBinary変換値を復元する
* @param c BASE64形式の文字
* @return Binary変換値
*/
private static int base64DecodeGetValue(char c) {
if (c >= 'A' && c <= 'Z') return c - 'A';
if (c >= 'a' && c <= 'z') return c - 'a' + 26;
if (c >= '0' && c <= '9') return c - '0' + 52;
if (c == '+') return 62;
if (c == '/') return 63;
if (c == '=') return 0;
return -1;
}
}