001/* 002 * Copyright (c) 2009 The openGion Project. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 013 * either express or implied. See the License for the specific language 014 * governing permissions and limitations under the License. 015 */ 016package org.opengion.fukurou.util; 017 018import java.io.File; 019import java.io.IOException; 020import java.io.PrintWriter; 021import java.net.HttpURLConnection; 022import java.net.MalformedURLException; 023import java.net.URL; 024import java.util.Arrays; 025import java.util.ArrayList; 026import java.util.List; 027import java.nio.file.Files; 028import java.nio.file.Paths; 029 // import java.nio.charset.Charset; 030import java.nio.charset.StandardCharsets; 031import java.util.concurrent.TimeUnit; // 8.0.0.0 (2021/07/31) Add 032 033// 8.0.0.0 (2021/07/31) httpclient-4.5.5.jar → httpclient5-5.1.jar 034// org.apache.http → org.apache.hc.core5.http or org.apache.hc.client5.http 035import org.apache.hc.core5.http.Header; 036import org.apache.hc.core5.http.HttpEntity; 037import org.apache.hc.core5.http.HttpHost; 038// import org.apache.hc.core5.http.message.StatusLine; // 8.0.0.0 (2021/07/31) Delete 039import org.apache.hc.client5.http.auth.AuthScope; 040import org.apache.hc.client5.http.auth.Credentials; 041import org.apache.hc.client5.http.auth.UsernamePasswordCredentials; 042import org.apache.hc.client5.http.config.RequestConfig; 043// import org.apache.http.client.config.CookieSpecs; // 8.0.0.0 (2021/07/31) Delete 044// import org.apache.hc.client5.http.auth.CredentialsProvider; // 8.0.0.0 (2021/07/31) Delete 045import org.apache.hc.client5.http.entity.UrlEncodedFormEntity; 046import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; 047import org.apache.hc.client5.http.classic.methods.HttpGet; 048import org.apache.hc.client5.http.classic.methods.HttpPost; 049//import org.apache.http.client.methods.HttpUriRequest; // 8.0.0.0 (2021/07/31) 050import org.apache.hc.core5.http.ClassicHttpRequest; 051import org.apache.hc.core5.http.ContentType; 052import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder; 053// import org.apache.hc.client5.http.entity.mime.HttpMultipartMode; // 8.0.0.0 (2021/07/31) Delete 054import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider; 055import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; 056import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; 057import org.apache.hc.core5.http.message.BasicHeader; 058import org.apache.hc.core5.http.message.BasicNameValuePair; 059import org.apache.hc.core5.http.NameValuePair; 060import org.apache.hc.core5.http.io.entity.EntityUtils; 061// import org.apache.hc.client5.http.impl.classic.HttpClients; 062import org.apache.hc.client5.http.cookie.CookieStore; 063// import org.apache.hc.core5.http.io.entity.StringEntity; // 8.0.0.0 (2021/07/31) Delete 064// import org.apache.http.impl.client.DefaultHttpClient;; 065import org.apache.hc.client5.http.protocol.HttpClientContext; 066// import java.io.UnsupportedEncodingException; // 8.0.0.0 (2021/07/31) Delete 067import org.apache.hc.core5.http.ParseException; // 8.0.0.0 (2021/07/31) Add 068 069import org.apache.hc.client5.http.cookie.BasicCookieStore; 070// import org.apache.hc.client5.http.cookie.Cookie; 071import java.net.URI; 072import java.net.URISyntaxException; 073import org.apache.hc.core5.http.io.support.ClassicRequestBuilder; 074 075// import org.apache.http.impl.client.DefaultRedirectStrategy; 076// import org.apache.http.HttpRequest; 077// import org.apache.http.HttpResponse; 078// import org.apache.http.protocol.HttpContext; 079// import org.apache.http.ProtocolException; 080// import org.apache.http.impl.client.LaxRedirectStrategy; // 8.0.0.0 (2021/07/31) Delete 081 082// import org.opengion.fukurou.system.Closer; 083import org.opengion.fukurou.system.LogWriter; 084import org.opengion.fukurou.system.OgRuntimeException ; 085 086import static org.opengion.fukurou.system.HybsConst.BUFFER_MIDDLE; 087import static org.opengion.fukurou.system.HybsConst.CR; 088 089/** 090 * HttpConnect は、指定のURL にアクセスして、データを取得します。 091 * URL へのアクセスにより、エンジンでは各種処理を実行させることが可能になります。 092 * 例えば、帳票デーモンの起動や、長時間かかる処理の実行などです。 093 * なお、URLに引数が付く場合は、ダブルコーテーションで括って下さい。 094 * URL の指定は、先頭に何もつけませ。指定の順番も関係ありません。 095 * - 付き引数は、指定順番は、関係ありません。 096 * 先頭が # の引数は、コメントと判断します。 097 * 098 * <pre> 099 * Usage: java org.opengion.fukurou.util.HttpConnect [-post=キー:ファイル名] … url [user:passwd] 100 * args[A] : url URLを指定します。GETの場合、パラメータは ?KEY=VALです 101 * args[*] : [-param=key:value] POST/GET時のパラメータのキーと値を:で区切って指定します。(複数回指定可) 102 * args[*] : [-header=key:value] ヘッダーに設定するパラメータのキーと値を:で区切って指定します。(複数回指定可) 103 * args[*] : [-auth=user:pass] BASIC認証のエリアへのアクセス時のユーザーとパスワードを指定します 104 * args[*] : [-proxy=host:port] proxy を使用する場合のホストとポートを指定します。 105 * args[*] : [-timeout=3] 接続タイムアウト時間を(秒)で指定します(初期値:無指定) 106 * args[*] : [-encode=UTF-8] エンコードを指定します。(初期値は UTF-8) 107 * args[*] : [-out=ファイル名] 結果をファイルに出力します。初期値は標準出力です 108 * args[*] : [-download=ファイル名] ファイル名を指定して、ダウンロードします 109 * args[*] : [-upload=ファイル名] ファイル名を指定して、multipart/form-dataでファイルアップロードします 110 * args[*] : [-postRedirect=true] POST時に強制的にリダイレクトを行います(GET時は自動でリダイレクトします)(初期値:false) 7.2.5.0 (2020/06/01) 111 * args[*] : [-errEx=true/false] trueの場合、レスポンスコードが、4XX,5XX の時に RuntimeException を投げます(初期値:false) 112 * args[*] : [#・・・・] コメント引数。(BATファイル上に残しておきたいが、使用したくない場合など) 113 * args[*] : [-debug=true/false] trueの場合、適度にデバッグ用のメッセージを出力します(初期値:false) 114 * </pre> 115 * 116 * ※ URLConnect との違い。 117 * -info/-data 等の区別の廃止。(実質、-info がなくなる。) 118 * setDownloadFile(String) 追加(-binaryの代用) 119 * setUploadFile(String) 追加 120 * proxy 設定の変更 121 * 122 * @og.rev 6.9.0.0 (2018/01/31) 新規作成 123 * 124 * @version 6.9.0.0 125 * @author Kazuhiko Hasegawa 126 * @since JDK8.0, 127 */ 128public class HttpConnect { 129 /** エンコードの初期値 {@value} */ 130 public static final String DEFAULT_CHARSET = "UTF-8" ; 131 /** 言語の初期値 {@value} */ 132 public static final String DEFAULT_LANG = "ja-JP" ; 133 /** User-Agentの初期値 {@value} */ 134 public static final String DEFAULT_AGENT = "openGion with Apache HttpClient" ; 135 /** GETで指定するときのURLの長さ制限 {@value} (IEの場合は、2,083文字) */ 136 public static final int MAX_GET_LENGTH = 2000 ; 137 138 private final String urlStr ; 139 private final String user ; 140 private final String pass ; 141 142 private int rpsCode = -1; 143 private String rpsMessage ; 144 private String charset = DEFAULT_CHARSET ; 145 private String upldFile ; 146 private String dwldFile ; // バイナリファイルとして受け取る場合のファイル名 147 private int timeout = -1; 148 private boolean isPost ; 149 private boolean postRedirect ; // 7.2.5.0 (2020/06/01) postRedirect(POST時に強制的にリダイレクト) 150 private boolean isDebug ; 151 152 private HttpHost proxy ; 153 154 private CookieStore ckStore ; // 8.0.0.0 (2021/07/31) 155 156 // 初期ヘッダー情報 157 private static final List<Header> INIT_HEADER = 158 Arrays.asList( 159 new BasicHeader( "Accept-Charset" , DEFAULT_CHARSET ) , 160 new BasicHeader( "Accept-Language" , DEFAULT_LANG ) , 161 new BasicHeader( "User-Agent" , DEFAULT_AGENT ) 162 ); 163 164 private final List<NameValuePair> reqParamList = new ArrayList<NameValuePair>(); // リクエストパラメーター(主にPOST時) 165 private final List<Header> headers = new ArrayList<>( INIT_HEADER ); // ヘッダーパラメーター 166 167 // GET でのパラメータのマージ。きちんとした方法がわかるまでの暫定処置 168 private final StringBuilder reqParamBuf = new StringBuilder( BUFFER_MIDDLE ); 169 170 /** 171 * 接続先URLと、認証用ユーザー:パスワードを指定する、コンストラクター 172 * 173 * 認証が必要ない場合は、userPass は、null でかまいません。 174 * 接続先URLは、HttpConnect で、urlEncode しますので、そのままの文字列でかまいません。 175 * 176 * @og.rev 6.9.0.0 (2018/01/31) 新規作成 177 * @og.rev 8.0.0.0 (2021/07/31) httpclient4 → httpclient5 対応 178 * 179 * @param url 接続するアドレスを指定します。(http://server:port/dir/file.html) 180 * @param userPass ユーザー:パスワード(認証接続が必要な場合) 181 */ 182 public HttpConnect( final String url, final String userPass ) { 183 urlStr = StringUtil.urlEncode2( url ); 184 185 if( StringUtil.isNull( userPass ) ) { 186 user = null; 187 pass = null; 188 } 189 else { 190 final String[] prm = StringUtil.csv2Array( userPass , ':' , 2 ); 191 user = prm[0]; 192 pass = prm[1]; 193 } 194 } 195 196// /** 197// * Form認証でのログイン 198// * 199// * https://hc.apache.org/httpcomponents-client-5.1.x/examples.html 200// * https://github.com/apache/httpcomponents-client/blob/5.1.x/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ClientFormLogin.java 201// * 202// * @og.rev 8.0.0.0 (2021/07/31) httpclient4 → httpclient5 対応 203// */ 204// private String formLogin() { 205// String body = null; 206// String secCheckURL = null; 207// 208// final BasicCookieStore cookieStore = new BasicCookieStore(); 209// try (final CloseableHttpClient httpclient = HttpClients.custom() 210// .setDefaultCookieStore(cookieStore) 211// .build()) { 212//// final HttpGet httpget = new HttpGet(urlStr); 213// final URI uri = new URI(urlStr); // j_security_check のアドレスを取るために。 214// final HttpGet httpget = new HttpGet(uri); 215// 216// try (final CloseableHttpResponse response1 = httpclient.execute(httpget)) { 217// final HttpEntity entity = response1.getEntity(); 218// 219// System.out.println("Login form get: " + response1.getCode() + " " + response1.getReasonPhrase()); 220// final String loginBody = EntityUtils.toString( entity, charset ); 221// // 一旦Form認証画面のHTMLが返ってくるので、その中から j_security_check を探してくる。 222// final int ed = loginBody.indexOf( "j_security_check" ); 223// if( ed >= 0 ) { 224// final int st = loginBody.lastIndexOf( '"',ed ); // 逆順に探す。 225// if( st >= 0 ) { 226// secCheckURL = uri.getScheme() + "://" + uri.getHost() + ':' + uri.getPort() 227// + loginBody.substring( st+1,ed ) + "j_security_check" ; 228// System.out.println(secCheckURL); 229// } 230// } 231// 232// EntityUtils.consume(entity); // リソースを解放 233// 234// // System.out.println("Initial set of cookies:"); 235// // final List<Cookie> cookies = cookieStore.getCookies(); 236// // if (cookies.isEmpty()) { 237// // System.out.println("None"); 238// // } else { 239// // for (int i = 0; i < cookies.size(); i++) { 240// // System.out.println("- " + cookies.get(i)); 241// // } 242// // } 243// } 244// 245// final ClassicHttpRequest login = ClassicRequestBuilder.post() 246// // .setUri(new URI("http://localhost:8828/gf/jsp/j_security_check")) 247// .setUri(new URI( secCheckURL )) 248// .addParameter("j_username", user) 249// .addParameter("j_password", pass) 250// .addParameter("j_security_check", "login") 251// .build(); 252// try (final CloseableHttpResponse response2 = httpclient.execute(login)) { 253// final HttpEntity entity = response2.getEntity(); 254// 255// System.out.println("Login form get: " + response2.getCode() + " " + response2.getReasonPhrase()); 256// body = EntityUtils.toString( entity, charset ); 257// 258// EntityUtils.consume(entity); // リソースを解放 259// 260// // System.out.println("Post logon cookies:"); 261// // final List<Cookie> cookies = cookieStore.getCookies(); 262// // if (cookies.isEmpty()) { 263// // System.out.println("None"); 264// // } else { 265// // for (int i = 0; i < cookies.size(); i++) { 266// // System.out.println("- " + cookies.get(i)); 267// // } 268// // } 269// } 270// } 271// catch( IOException ex ) { ex.printStackTrace(); } 272// catch( URISyntaxException ex ) { ex.printStackTrace(); } 273// catch( final ParseException ex ) {ex.printStackTrace();} 274// 275// return body ; 276// } 277 278 /** 279 * Form認証でのログイン 280 * 281 * https://hc.apache.org/httpcomponents-client-5.1.x/examples.html 282 * https://github.com/apache/httpcomponents-client/blob/5.1.x/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ClientFormLogin.java 283 * 284 * @og.rev 8.0.0.0 (2021/07/31) httpclient4 → httpclient5 対応 285 */ 286// private String formLogin( final CloseableHttpClient client , final URI uri ) { 287 private String formLogin( final CloseableHttpClient client , final ClassicHttpRequest method ) { 288 String body = null; 289 290 try { 291 final URI uri = method.getUri(); 292 final URI secCheckURI = uri.resolve( "j_security_check" ); 293 if( isDebug ) { System.out.println( "secCheckURI URL=" + secCheckURI ); } 294 295 final ClassicHttpRequest login = ClassicRequestBuilder.post() 296 // .setUri(new URI("http://localhost:8828/gf/jsp/j_security_check")) 297 .setUri( secCheckURI ) 298 .addParameter("j_username", user) 299 .addParameter("j_password", pass) 300 .addParameter("j_security_check", "login") 301 .build(); 302 303 // うまくいかない。 304 // // アップロードの場合、自身のEntityを再セットしてやる。 305 // if( !StringUtil.isNull( upldFile ) ) { 306 // final File file = new File( upldFile ); 307 // if( isDebug ) { System.out.println( " MULTI FILE=" + file ); } 308 // final HttpEntity entity = MultipartEntityBuilder.create() 309 // .setCharset( StandardCharsets.UTF_8 ) // ファイル名の文字化け対策 310 // .addBinaryBody( "upload" , 311 // file , 312 // ContentType.DEFAULT_BINARY , 313 // file.getName() ) 314 // .build(); 315 // login.setEntity( entity ); 316 // } 317 318 try( CloseableHttpResponse response = client.execute(login) ) { 319 final HttpEntity entity = response.getEntity(); 320 321 rpsCode = response.getCode(); // 8.0.0.0 (2021/07/31) 322 rpsMessage = code2Message( rpsCode ).trim(); // 8.0.0.0 (2021/07/31) 323 324 // Form認証の場合、バイナリ処理は、formLogin 内で行います。 325 // バイナリファイルとして受け取る場合。成功(200番台)のみ処理します。 326 if( !StringUtil.isNull( dwldFile ) && rpsCode >= 200 && rpsCode < 300 ) { 327 Files.write( Paths.get( dwldFile ) , EntityUtils.toByteArray( entity ) ); 328 body = dwldFile; 329 } 330 else { 331 body = EntityUtils.toString( entity, charset ); 332 } 333 EntityUtils.consume(entity); // リソースを解放 334 } 335 } 336 catch( final IOException | URISyntaxException | ParseException ex ) { 337 throw new OgRuntimeException( ex ); 338 } 339 340 return body ; 341 } 342 343 /** 344 * URL接続先のデータを取得します。 345 * 346 * この処理の前に、必要な情報を設定して置いてください。 347 * また、code や message は、このメソッドを実行しないと取得できませんのでご注意ください。 348 * 349 * 取得したデータは、指定のURL へのアクセスのみです。 350 * 通常のWebブラウザは、イメージや、JavaScriptファイル、CSSファイルなど、 351 * 各種ファイル毎にHTTP接続を行い、取得して、レンダリングします。 352 * このメソッドでの処理では、それらのファイル内に指定されているURLの 353 * 再帰的な取得は行いません。 354 * よって、フレーム処理なども行いません。 355 * 356 * @og.rev 6.9.0.0 (2018/01/31) 新規作成 357 * @og.rev 8.0.0.0 (2021/07/31) httpclient4 → httpclient5 対応 358 * 359 * @return 接続結果 360 * @og.rtnNotNull 361 * @throws IOException 入出力エラーが発生したとき 362 * @throws MalformedURLException URLの形式が間違っている場合 363 */ 364 public String readData() throws IOException , MalformedURLException { 365 // HttpUriRequest method ; 366 final ClassicHttpRequest method ; // 8.0.0.0 (2021/07/31) 367 if( isPost ) { 368 if( isDebug ) { System.out.println( "POST URL=" + urlStr ); } 369 method = new HttpPost( urlStr ); 370 371 if( !reqParamList.isEmpty() ) { 372 // ((HttpPost)method).setEntity( new UrlEncodedFormEntity( reqParamList , DEFAULT_CHARSET ) ); 373 method.setEntity( new UrlEncodedFormEntity( reqParamList ) ); // 8.0.0.0 (2021/07/31) 374 if( isDebug ) { reqParamList.forEach( v -> System.out.println( "PARAM KEY=" + v.getName() + " , VAL=" + v.getValue() ) ); } 375 } 376 377 if( !StringUtil.isNull( upldFile ) ) { 378 final File file = new File( upldFile ); 379 if( isDebug ) { System.out.println( " MULTI FILE=" + file ); } 380 final HttpEntity entity = MultipartEntityBuilder.create() 381 // .setMode( HttpMultipartMode.BROWSER_COMPATIBLE ) // 8.0.0.0 (2021/07/31) Delete 382 .setCharset( StandardCharsets.UTF_8 ) // ファイル名の文字化け対策 383 .addBinaryBody( "upload" , 384 file , 385 ContentType.DEFAULT_BINARY , 386 file.getName() ) 387 .build(); 388 // ((HttpPost)method).setEntity( entity ); 389 method.setEntity( entity ); 390 } 391 } 392 else { 393 // GET でのパラメータのマージ。きちんとした方法がわかるまでの暫定処置 394 final String getStr = reqParamBuf.length() == 0 395 ? urlStr 396 : reqParamBuf.toString() ; 397 398 if( isDebug ) { System.out.println( "GET URL=" + getStr ); } 399 400 method = new HttpGet( getStr ); 401 } 402 403 final HttpClientContext context = HttpClientContext.create(); 404// if( ckStore != null ) { // 8.0.0.0 (2021/07/31) 未使用 405// context.setCookieStore(ckStore); 406// } 407 408 String body = null; 409 try( CloseableHttpClient client = getClient() ; 410 CloseableHttpResponse response = client.execute(method,context) ) { 411 412 // final StatusLine status = response.getStatusLine(); // 8.0.0.0 (2021/07/31) Delete 413 // rpsCode = status.getStatusCode(); 414 // rpsMessage = ( code2Message( rpsCode ) + CR + status.getReasonPhrase() ).trim(); 415 416 rpsCode = response.getCode(); // 8.0.0.0 (2021/07/31) 417 if( isDebug ) { System.out.println( "rpsCode=" + rpsCode ); } 418 rpsMessage = code2Message( rpsCode ).trim(); // 8.0.0.0 (2021/07/31) 419 420 final HttpEntity entity = response.getEntity(); 421 422 if( entity == null ) { 423 body = rpsMessage; // HttpEntity が受け取れなかった場合は、メッセージを表示します。 424 } 425 else { 426 // body は一度しか処理できない。EntityUtils.toByteArray( entity ) か、EntityUtils.toString( entity, charset ); 427 428 // バイナリファイルとして受け取る場合。成功(200番台)のみ処理します。 429 if( !StringUtil.isNull( dwldFile ) && rpsCode >= 200 && rpsCode < 300 ) { 430 final byte[] dwnBody = EntityUtils.toByteArray( entity ); 431 final String text = new String( dwnBody,charset ); 432 433 // 一旦Form認証画面のHTMLが返ってくるので、その中から j_security_check を探してくる。 434 if( text.contains( "j_security_check" ) ) { 435 body = formLogin( client,method ); // Form認証時の再接続処理 436 } 437 else { 438 Files.write( Paths.get( dwldFile ) , dwnBody ); 439 body = dwldFile; 440 } 441 } 442 else { 443 // form認証チェックが必要なので、バイナリでも文字列で受け取る。 444 body = EntityUtils.toString( entity, charset ); 445 446 // 一旦Form認証画面のHTMLが返ってくるので、その中から j_security_check を探してくる。 447 if( body.contains( "j_security_check" ) ) { 448 body = formLogin( client,method ); // Form認証時の再接続処理 449 } 450 } 451 } 452 EntityUtils.consume(entity); // リソースを解放 453 454// // バイナリファイルとして受け取る場合。成功(200番台)のみ処理します。 455// if( !StringUtil.isNull( dwldFile ) && rpsCode >= 200 && rpsCode < 300 ) { 456// Files.write( Paths.get( dwldFile ) , EntityUtils.toByteArray( entity ) ); 457// body = dwldFile; 458// } 459// else { 460// if( entity == null ) { 461// body = rpsMessage; // HttpEntity が受け取れなかった場合は、メッセージを表示します。 462// } 463// else { 464// body = EntityUtils.toString( entity, charset ); 465// } 466// } 467 } 468 // 8.0.0.0 (2021/07/31) Add 469 catch( final ParseException ex ) { 470 throw new OgRuntimeException( ex ); 471 } 472 473 return body; 474 } 475 476 /** 477 * 接続先の HttpClient オブジェクトを作成します。 478 * 479 * 接続に必要な情報を、設定します。 480 * CloseableHttpClient は、AutoCloseable を継承しています。 481 * 482 * 7.2.5.0 (2020/06/01) 483 * 通常、HttpClientはGETの場合は自動でリダイレクト処理しますが、 484 * POSTの場合は、302が返るだけでリダイレクト処理しません。 485 * http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3[HTTP RFC 2616]で規定されています。 486 * ここでは、ダウンロードファイルがあり、POSTの場合だけ強制的に 487 * 488 * @og.rev 6.9.0.0 (2018/01/31) 新規作成 489 * @og.rev 7.2.5.0 (2020/06/01) postRedirect(POST時に強制的にリダイレクト) 490 * @og.rev 8.0.0.0 (2021/07/31) httpclient4 → httpclient5 対応 491 * 492 * @return HttpConnectionオブジェクト 493 * @throws IOException 入出力エラーが発生したとき 494 */ 495 private CloseableHttpClient getClient() throws MalformedURLException { 496 497 final HttpClientBuilder clBuild = HttpClientBuilder.create(); 498 499 final BasicCookieStore cookieStore = new BasicCookieStore(); 500 clBuild.setDefaultCookieStore(cookieStore) ; 501 502 // request configuration 503// RequestConfig.Builde.setCookieSpec( CookieSpecs.STANDARD ); // 最新のRFC準拠ヘッダーを理解するのが困難なので。 8.0.0.0 (2021/07/31) Delete 504 505 if( timeout >= 0 ) { 506 final RequestConfig.Builder reqConfig = RequestConfig.custom(); 507 // reqConfig.setConnectTimeout( timeout * 1000 ) // timeoutの単位は(秒)、設定値は、ミリ秒 508 // .setSocketTimeout( timeout * 1000 ); 509 reqConfig.setConnectTimeout( timeout ,TimeUnit.SECONDS ); // 8.0.0.0 (2021/07/31) timeoutの単位は(秒) 510 511 clBuild.setDefaultRequestConfig( reqConfig.build() ); 512 } 513 514 // 7.2.5.0 (2020/06/01) postRedirect(POST時に強制的にリダイレクト) 515 // 8.0.0.0 (2021/07/31) httpclient5-5.1対応により LaxRedirectStrategy 廃止の為一旦削除 516 // if( postRedirect ) { 517 // clBuild.setRedirectStrategy( new LaxRedirectStrategy() ); 518 // } 519 520 // headers (初期設定も入っているので、通常は、empty にはならない。) 521 if( !headers.isEmpty() ) { 522 clBuild.setDefaultHeaders( headers ); 523 } 524 525 // Proxy 526 if( proxy != null ) { 527 clBuild.setProxy( proxy ); 528 } 529 530 // Auth 531 // https://github.com/apache/httpcomponents-client/blob/5.1.x/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ClientAuthentication.java 532 if( !StringUtil.isNull( user ) ) { 533 final URL url = new URL( urlStr ); 534 final AuthScope scope = new AuthScope( url.getHost(), url.getPort() ); 535 // final Credentials cred = new UsernamePasswordCredentials( user ,pass ); 536 final Credentials cred = new UsernamePasswordCredentials( user ,pass.toCharArray() ); // 8.0.0.0 (2021/07/31) 537 538 // final CredentialsProvider credProvider = new BasicCredentialsProvider(); 539 final BasicCredentialsProvider credProvider = new BasicCredentialsProvider(); // 8.0.0.0 (2021/07/31) 540 credProvider.setCredentials( scope,cred ); 541 clBuild.setDefaultCredentialsProvider( credProvider ); 542 } 543 544 // // (デフォルトのHttpClientは、最新のRFC準拠ヘッダーを理解するのが困難です。) 545 // // RequestConfig に、CookieSpecs.STANDARD を設定しているが、効果なければ、使わなくしてしまう。 546 // clBuild.disableCookieManagement(); 547 548 return clBuild.build(); // HttpClient httpClient = HttpClientBuilder.create().*****.build(); 549 } 550 551 /** 552 * 接続先に使用する引数(パラメータ)を追加します。 553 * 554 * これは、POSTでも、GETでも使用できます。 555 * POSTの場合は、NameValuePair として、HttpPost に、Entity としてセットするデータを設定します。 556 * GET の場合は、既存の接続先URLに、&キー=値・・・・ で、追記します。 557 * すでに、パラメータが指定済みの場合は、& で、そうでなければ、? で連結します。 558 * ここで指定するパラメータは、内部で、urlEncode しますので、そのままの文字列でかまいません。 559 * 560 * デフォルトは、GETですが、Internet Explorer では URL に最大 2,083 文字しか指定できないため、 561 * それ以上の場合は、POST に自動で切り替えます。 562 * 563 * @og.rev 6.9.0.0 (2018/01/31) 新規作成 564 * 565 * @param key パラメータキー(nullの場合は、登録しません) 566 * @param val パラメータ値 567 */ 568 public void addRequestProperty( final String key, final String val ) { 569 if( !StringUtil.isNull( key ) ) { 570 reqParamList.add( new BasicNameValuePair( key,val ) ); // POST のときのパラメータ。(GETでも使えるはず?) 571 572 if( !isPost ) { // 明らかに、GET でない場合は、この処理を行わない。 573 if( reqParamBuf.length() == 0 ) { // 初めての場合 574 reqParamBuf.append( urlStr ) 575 .append( urlStr.indexOf( '?' ) > 0 ? '&' : '?' ) 576 .append( StringUtil.urlEncode2( key ) ) 577 .append( '=' ) 578 .append( StringUtil.urlEncode2( val ) ); // null のときは、長さゼロ文字列になる。 579 } 580 else if( reqParamBuf.length() > MAX_GET_LENGTH ) { 581 if( isDebug ) { System.out.println( "GET → POST変更: URLの長さ制限<" + reqParamBuf.length() ); } 582 isPost = true; // GETで送れるURLの長さ制限を超えた場合は、POSTにする。 583 } 584 else { 585 reqParamBuf.append( '&' ) 586 .append( StringUtil.urlEncode2( key ) ) 587 .append( '=' ) 588 .append( StringUtil.urlEncode2( val ) ); // null のときは、長さゼロ文字列になる。 589 } 590 } 591 } 592 } 593 594 /** 595 * setRequestPropertyでセットするデータを設定します。 596 * 597 * keys,vals各々、カンマ区切りで分解します。 598 * 599 * @og.rev 5.10.16.0 (2019/10/04) 追加 600 * 601 * @param keys パラメータキー(カンマ区切り) 602 * @param vals パラメータ(カンマ区切り) 603 */ 604 public void setRequestProperty( final String keys, final String vals ) { 605 if( keys != null && keys.length() > 0 && vals != null && vals.length() > 0 ){ 606 final String[] propKeys = StringUtil.csv2Array( keys ); 607 final String[] propVals = StringUtil.csv2Array( vals ); 608 609 if( propKeys.length == propVals.length && propKeys.length > 0 ) { 610 for( int i=0; i<propKeys.length; i++ ) { 611 addRequestProperty( propKeys[i], propVals[i] ); 612 } 613 } 614 else { 615 final String errMsg = "パラメータのキーと、値の数が一致しません。" + CR 616 + " key=[" + keys + "]" + CR 617 + " val=[" + vals + "]" ; 618 throw new IllegalArgumentException( errMsg ); 619 } 620 } 621 } 622 623 /** 624 * 指定のURLに対して、コネクトするのに使用するプロキシ設定を行います。 625 * このときに、ヘッダー情報を内部変数に設定しておきます。 626 * 627 * @og.rev 6.9.0.0 (2018/01/31) 新規作成 628 * 629 * @param host 接続するプロキシのホスト名(nullの場合は、登録しません) 630 * @param port 接続するプロキシのポート番号 631 */ 632 public void setProxy( final String host,final int port ) { 633 if( !StringUtil.isNull( host ) ) { 634 proxy = new HttpHost( host , port ); 635 } 636 } 637 638 /** 639 * Header として、HttpClient にセットするデータを設定します。 640 * 641 * 例えばJSON形式でPOSTする場合は通常"Content-Type", "application/json"を指定します。 642 * 643 * @og.rev 6.9.0.0 (2018/01/31) 新規作成 644 * 645 * @param key パラメータキー(nullの場合は、登録しません) 646 * @param val パラメータ値(nullの場合は、登録しません) 647 */ 648 public void addHeaderProperty( final String key, final String val ) { 649 if( !StringUtil.isNull( key ) && !StringUtil.isNull( val ) ) { 650 headers.add( new BasicHeader( key,val ) ); 651 } 652 } 653 654 /** 655 * URL接続先のバイナリファイルをダウンロード取得します。 656 * 657 * 取得したファイルは、dwldFile にバイナリのまま書き込まれます。 658 * よって、エンコードの指定は不要です。 659 * 660 * @og.rev 6.9.0.0 (2018/01/31) 新規作成 661 * 662 * @param dwldFile ダウンロードするファイル名。 663 * @throws IOException 入出力エラーが発生したとき 664 */ 665 public void setDownloadFile( final String dwldFile ) throws IOException { 666 this.dwldFile = dwldFile; 667 } 668 669 /** 670 * URL接続先のバイナリファイルをアップロードします。 671 * 672 * 取得したファイルは、upldFile にバイナリのまま書き込まれます。 673 * よって、エンコードの指定は不要です。 674 * アップロード は、multipart/form-data で送信するため、isPost = true を 675 * 内部的に設定しておきます。 676 * 677 * @og.rev 6.9.0.0 (2018/01/31) 新規作成 678 * @og.rev 7.2.5.0 (2020/06/01) upldFileのnull判定を入れます。 679 * 680 * @param upldFile アップロードするファイル名。 681 * @throws IOException 入出力エラーが発生したとき 682 */ 683 public void setUploadFile( final String upldFile ) throws IOException { 684 if( upldFile != null ) { 685 this.upldFile = upldFile; 686 isPost = true; 687 } 688 } 689 690 /** 691 * エンコード情報を設定します。 692 * 693 * 初期値は、UTF-8 です。 694 * 695 * @og.rev 6.9.0.0 (2018/01/31) 新規作成 696 * 697 * @param chset エンコード情報(nullの場合は、初期値:UTF-8 になります) 698 */ 699 public void setCharset( final String chset ) { 700 if( !StringUtil.isNull( chset ) ) { 701 charset = chset; 702 } 703 } 704 705 /** 706 * 接続タイムアウト時間を(秒)で指定します 707 * 708 * 実際には、org.apache.http.client.config.RequestConfig に対して、 709 * .setConnectTimeout( timeout * 1000 ) 710 * .setSocketTimeout( timeout * 1000 ) 711 * のように、 1000倍して設定しています。 712 * 0 は、無限のタイムアウト、マイナスは、設定しません。(つまりJavaの初期値のまま) 713 * 714 * @og.rev 6.9.0.0 (2018/01/31) 新規作成 715 * 716 * @param tout タイムアウト時間(秒) (ゼロは、無制限) 717 */ 718 public void setTimeout( final int tout ) { 719 timeout = tout; 720 } 721 722 /** 723 * trueの場合、POSTを使用して接続します(初期値:false)。 724 * 725 * 通常はGETですが、外部から強制的に、POSTで送信したい場合に、 726 * 設定します。 727 * ただし、バイナリファイルをアップロードか、URLの長さ制限が、 728 * {@value #MAX_GET_LENGTH} を超えた場合は、内部で自動的に、post にします。 729 * 730 * @og.rev 6.9.0.1 (2018/02/05) 新規作成 731 * 732 * @param usePost true:POST使用/false:通常(GET) 733 */ 734 public void usePost( final boolean usePost ) { 735 isPost = usePost; 736 } 737 738 /** 739 * trueの場合、POST時に強制的にリダイレクトを行います(初期値:false)。 740 * 741 * @og.rev 7.2.5.0 (2020/06/01) postRedirect(POST時に強制的にリダイレクト) 742 * @og.rev 8.0.0.0 (2021/07/31) httpclient5-5.1対応により LaxRedirectStrategy 廃止の為一旦削除 743 * 744 * @param useRedirect true:POST時に強制的にリダイレクト/false:通常 745 */ 746 public void setPostRedirect( final boolean useRedirect ) { 747 postRedirect = useRedirect; 748 } 749 750 /** 751 * trueの場合、適度にデバッグ用のメッセージを出力します(初期値:false)。 752 * 753 * @og.rev 6.9.0.0 (2018/01/31) 新規作成 754 * 755 * @param isDebug true:デバッグ用のメッセージを出力/false:通常 756 */ 757 public void setDebug( final boolean isDebug ) { 758 this.isDebug = isDebug; 759 } 760 761 /** 762 * 実行結果のステータスコード 情報を取得します。 763 * 764 * 結果は、#readData() メソッドをコールしないと取れません。 765 * 未実行の場合は、-1 がセットされています。 766 * 767 * @og.rev 6.9.0.0 (2018/01/31) 新規作成 768 * 769 * @return 結果コード 情報 770 * @see #readData() 771 */ 772 public int getCode() { return rpsCode; } 773 774 /** 775 * メッセージ 情報を取得します。 776 * 777 * 結果は、#readData() メソッドをコールしないと取れません。 778 * 未実行の場合は、null がセットされています。 779 * 780 * @og.rev 6.9.0.0 (2018/01/31) 新規作成 781 * 782 * @return メッセージ 情報 783 */ 784 public String getMessage() { return rpsMessage; } 785 786 /** 787 * HttpURLConnection のレスポンスコードに対応するメッセージ文字列を返します。 788 * 789 * HttpURLConnection の getResponseCode() メソッドにより取得された、HTTPレスポンスコード 790 * に対応する文字列を返します。この文字列は、HttpURLConnection で定義された 791 * static 定数のコメントを、定義しています。 792 * 793 * @og.rev 6.9.0.0 (2018/01/31) 新規作成 794 * 795 * @param code HTTPレスポンスコード 796 * 797 * @return レスポンスコードに対応する文字列 798 * @og.rtnNotNull 799 * @see HttpURLConnection#HTTP_ACCEPTED 800 */ 801 public static String code2Message( final int code ) { 802 final String msg ; 803 switch( code ) { 804 case 100 : msg = "100: 要求は続行可能です。" ; break; 805 case 101 : msg = "101: プロトコルを切り替えます。" ; break; 806 case HttpURLConnection.HTTP_OK : msg = "200: OK です。" ; break; 807 case HttpURLConnection.HTTP_CREATED : msg = "201: 作成されました。" ; break; 808 case HttpURLConnection.HTTP_ACCEPTED : msg = "202: 受け入れられました。" ; break; 809 case HttpURLConnection.HTTP_NOT_AUTHORITATIVE : msg = "203: 信頼できない情報です。" ; break; 810 case HttpURLConnection.HTTP_NO_CONTENT : msg = "204: コンテンツがありません。" ; break; 811 case HttpURLConnection.HTTP_RESET : msg = "205: コンテンツをリセットします。" ; break; 812 case HttpURLConnection.HTTP_PARTIAL : msg = "206: 部分的なコンテンツです。" ; break; 813 case HttpURLConnection.HTTP_MULT_CHOICE : msg = "300: 複数の選択肢があります。" ; break; 814 case HttpURLConnection.HTTP_MOVED_PERM : msg = "301: 永続的に移動されました。" ; break; 815 case HttpURLConnection.HTTP_MOVED_TEMP : msg = "302: 一時的なリダイレクト。" ; break; 816 case HttpURLConnection.HTTP_SEE_OTHER : msg = "303: ほかを参照してください。" ; break; 817 case HttpURLConnection.HTTP_NOT_MODIFIED : msg = "304: 変更されていません。" ; break; 818 case HttpURLConnection.HTTP_USE_PROXY : msg = "305: プロキシを使用します。" ; break; 819 case 306 : msg = "306: 仕様の拡張案です。" ; break; 820 case 307 : msg = "307: 一時的なリダイレクトです。" ; break; 821 case HttpURLConnection.HTTP_BAD_REQUEST : msg = "400: 不当な要求です。" ; break; 822 case HttpURLConnection.HTTP_UNAUTHORIZED : msg = "401: 認証されませんでした。" ; break; 823 case HttpURLConnection.HTTP_PAYMENT_REQUIRED : msg = "402: 支払いが必要です。" ; break; 824 case HttpURLConnection.HTTP_FORBIDDEN : msg = "403: 禁止されています。" ; break; 825 case HttpURLConnection.HTTP_NOT_FOUND : msg = "404: 見つかりませんでした。" ; break; 826 case HttpURLConnection.HTTP_BAD_METHOD : msg = "405: メソッドは許可されません。" ; break; 827 case HttpURLConnection.HTTP_NOT_ACCEPTABLE : msg = "406: 受け入れられません。" ; break; 828 case HttpURLConnection.HTTP_PROXY_AUTH : msg = "407: プロキシの認証が必要です。" ; break; 829 case HttpURLConnection.HTTP_CLIENT_TIMEOUT : msg = "408: 要求がタイムアウトしました。" ; break; 830 case HttpURLConnection.HTTP_CONFLICT : msg = "409: 重複しています。" ; break; 831 case HttpURLConnection.HTTP_GONE : msg = "410: 存在しません。" ; break; 832 case HttpURLConnection.HTTP_LENGTH_REQUIRED : msg = "411: 長さが必要です。" ; break; 833 case HttpURLConnection.HTTP_PRECON_FAILED : msg = "412: 前提条件が満たされていません。" ; break; 834 case HttpURLConnection.HTTP_ENTITY_TOO_LARGE : msg = "413: 要求のエンティティが大きすぎます。" ; break; 835 case HttpURLConnection.HTTP_REQ_TOO_LONG : msg = "414: 要求のURIが大きすぎます。" ; break; 836 case HttpURLConnection.HTTP_UNSUPPORTED_TYPE : msg = "415: サポートされないメディアタイプです。" ; break; 837 case 416 : msg = "416: 要求された範囲は不十分です。" ; break; 838 case 417 : msg = "417: 要求どおりの処理が不可能です。" ; break; 839 case HttpURLConnection.HTTP_INTERNAL_ERROR : msg = "500: 内部サーバエラーです。" ; break; 840 case HttpURLConnection.HTTP_NOT_IMPLEMENTED : msg = "501: 実装されていません。" ; break; 841 case HttpURLConnection.HTTP_BAD_GATEWAY : msg = "502: 誤ったゲートウェイです。" ; break; 842 case HttpURLConnection.HTTP_UNAVAILABLE : msg = "503: サービスが利用できません。" ; break; 843 case HttpURLConnection.HTTP_GATEWAY_TIMEOUT : msg = "504: ゲートウェイがタイムアウトしました。" ; break; 844 case HttpURLConnection.HTTP_VERSION : msg = "505: サポートされていないHTTPバージョンです。" ; break; 845 default : msg = code + ": 未定義" ; break; 846 } 847 return msg ; 848 } 849 850 /** 851 * サンプル実行用のメインメソッド 852 * 853 * <pre> 854 * Usage: java org.opengion.fukurou.util.HttpConnect [-post=キー:ファイル名] … url [user:passwd] 855 * args[A] : url URLを指定します。GETの場合、パラメータは ?KEY=VALです 856 * args[*] : [-param=key:value] POST/GET時のパラメータのキーと値を:で区切って指定します。(複数回指定可) 857 * args[*] : [-header=key:value] ヘッダーに設定するパラメータのキーと値を:で区切って指定します。(複数回指定可) 858 * args[*] : [-auth=user:pass] BASIC認証のエリアへのアクセス時のユーザーとパスワードを指定します 859 * args[*] : [-useForm=true/false] 認証方式にFORM認証を指定する場合、trueをセットします(初期値:false) 8.0.0.0 (2021/08/20) 860 * args[*] : [-proxy=host:port] proxy を使用する場合のホストとポートを指定します。 861 * args[*] : [-timeout=3] 接続タイムアウト時間を(秒)で指定します(初期値:無指定) 862 * args[*] : [-encode=UTF-8] エンコードを指定します。(初期値は UTF-8) 863 * args[*] : [-out=ファイル名] 結果をファイルに出力します。初期値は標準出力です 864 * args[*] : [-download=ファイル名] ファイル名を指定して、ダウンロードします 865 * args[*] : [-upload=ファイル名] ファイル名を指定して、multipart/form-dataでファイルアップロードします 866 * args[*] : [-postRedirect=true] POST時に強制的にリダイレクトを行います(GET時は自動でリダイレクトします)(初期値:false) 7.2.5.0 (2020/06/01) 867 * args[*] : [-usePost=true] POSTを強制的に使用する場合にセットします(初期値:false) 8.0.0.0 (2021/08/20) 868 * args[*] : [-errEx=true/false] trueの場合、レスポンスコードが、4XX,5XX の時に RuntimeException を投げます(初期値:false) 869 * args[*] : [#・・・・] コメント引数。(BATファイル上に残しておきたいが、使用したくない場合など) 870 * args[*] : [-debug=true/false] trueの場合、適度にデバッグ用のメッセージを出力します(初期値:false) 871 * </pre> 872 * 873 * @og.rev 6.9.0.0 (2018/01/31) 新規作成 874 * @og.rev 7.2.5.0 (2020/06/01) postRedirect(POST時に強制的にリダイレクト)引数を追加 875 * 876 * @param args コマンド引数配列 877 * @throws IOException 入出力エラーが発生したとき 878 */ 879 public static void main( final String[] args ) throws IOException { 880 if( args.length < 2 ) { 881 LogWriter.log( "Usage: java org.opengion.fukurou.util.HttpConnect [-data/-binary] … url" ); 882 LogWriter.log( " args[A] : url URLを指定します。GETの場合、パラメータは ?KEY=VALです" ); 883 LogWriter.log( " args[*] : [-param=key:value] POST/GET時のパラメータのキーと値を:で区切って指定します。(複数回指定可)" ); 884 LogWriter.log( " args[*] : [-header=key:value] ヘッダーに設定するパラメータのキーと値を:で区切って指定します。(複数回指定可)" ); 885 LogWriter.log( " args[*] : [-auth=user:pass] BASIC認証/FORM認証のエリアへのアクセス時のユーザーとパスワードを指定します" ); 886// LogWriter.log( " args[*] : [-useForm=true/false] 認証方式にFORM認証を指定する場合、trueをセットします(初期値:false)" ); 887 LogWriter.log( " args[*] : [-proxy=host:port] proxy を使用する場合のホストとポートを指定します。" ); 888 LogWriter.log( " args[*] : [-timeout=3] 接続タイムアウト時間を(秒)で指定します(初期値:無指定)" ); 889 LogWriter.log( " args[*] : [-encode=UTF-8] エンコードを指定します。(初期値は UTF-8)" ); 890 LogWriter.log( " args[*] : [-out=ファイル名] 結果をファイルに出力します。初期値は標準出力です" ); 891 LogWriter.log( " args[*] : [-download=ファイル名] ファイル名を指定して、ダウンロードします" ); 892 LogWriter.log( " args[*] : [-upload=ファイル名] ファイル名を指定して、multipart/form-dataでファイルアップロードします" ); 893 LogWriter.log( " args[*] : [-postRedirect=true] POST時に強制的にリダイレクトを行います(GET時は自動でリダイレクトします)(初期値:false)" ); 894 LogWriter.log( " args[*] : [-usePost=true] POSTを強制的に使用する場合にセットします(初期値:false)" ); 895 LogWriter.log( " args[*] : [-errEx=true/false] trueの場合、レスポンスコードが、4XX,5XX の時に RuntimeException を投げます(初期値:false)" ); 896 LogWriter.log( " args[*] : [#・・・・] コメント引数。(BATファイル上に残しておきたいが、使用したくない場合など)" ); 897 LogWriter.log( " args[*] : [-debug=true/false] trueの場合、適度にデバッグ用のメッセージを出力します(初期値:false)" ); 898 return; 899 } 900 901 String urlStr = null ; 902 final List<String> paramKey = new ArrayList<>(); // パラメーターキー 903 final List<String> paramVal = new ArrayList<>(); // パラメーター値 904 final List<String> headerKey = new ArrayList<>(); // パラメーターキー 905 final List<String> headerVal = new ArrayList<>(); // パラメーター値 906 907 String userPass = null ; // -auth 908// boolean useForm = false ; // -useForm // 8.0.0.0 (2021/08/20) 909 String proxy = null ; // -proxy 910 int timeout = -1 ; // -timeout 911 String encode = DEFAULT_CHARSET ; // -encode 912 String outFile = null ; // -out 913 String dwldFile = null ; // -download 914 String upldFile = null ; // -upload 915 boolean isEx = false ; // -errEx 916 boolean isDebug = false ; // -debug 917 boolean postRedirect = false ; // -postRedirect // 7.2.5.0 (2020/06/01) postRedirect(POST時に強制的にリダイレクト) 918 boolean nonWriter = false ; // -out 指定で見つからない場合 919 boolean isPost = false ; // -usePost 920 921// int code = -1; 922 923 for( final String arg : args ) { 924 if( arg.startsWith( "-param=" ) ) { 925 final String[] prm = StringUtil.csv2Array( arg.substring( "-param=".length() ) , '=' , 2 ); 926 paramKey.add( prm[0] ); 927 paramVal.add( prm[1] ); 928 } 929 else if( arg.startsWith( "-header=" ) ) { 930 final String[] prm = StringUtil.csv2Array( arg.substring( "-header=".length() ) , '=' , 2 ); 931 headerKey.add( prm[0] ); 932 headerVal.add( prm[1] ); 933 } 934 else if( arg.startsWith( "-auth=" ) ) { 935 userPass = arg.substring( "-auth=".length() ); 936 if( StringUtil.isNull( userPass ) ) { 937 System.err.println( arg + "指定した場合は、引数を設定してください。" ); 938 } 939 } 940// else if( arg.startsWith( "-useForm=" ) ) { 941// useForm = "true".equalsIgnoreCase( arg.substring( "-useForm=".length() ) ); 942// } 943 else if( arg.startsWith( "-proxy=" ) ) { 944 proxy = arg.substring( "-proxy=".length() ); 945 if( StringUtil.isNull( proxy ) ) { 946 System.err.println( arg + "指定した場合は、引数を設定してください。" ); 947 } 948 } 949 else if( arg.startsWith( "-timeout=" ) ) { 950 timeout = Integer.parseInt( arg.substring( "-timeout=".length() ) ); 951 } 952 else if( arg.startsWith( "-encode=" ) ) { 953 encode = arg.substring( "-encode=".length() ); 954 if( StringUtil.isNull( encode ) ) { 955 System.err.println( arg + "指定した場合は、引数を設定してください。" ); 956 } 957 } 958 else if( arg.startsWith( "-out=" ) ) { 959 outFile = arg.substring( "-out=".length() ); 960 if( StringUtil.isNull( outFile ) ) { 961 System.err.println( arg + "指定した場合は、引数を設定してください。" ); 962 } 963 else { 964 if( "null".equalsIgnoreCase( outFile ) || "none".equalsIgnoreCase( outFile ) ) { 965 outFile = null; 966 nonWriter = true; 967 } 968 } 969 } 970 else if( arg.startsWith( "-download=" ) ) { 971 dwldFile = arg.substring( "-download=".length() ); 972 if( StringUtil.isNull( dwldFile ) ) { 973 System.err.println( arg + "指定した場合は、引数を設定してください。" ); 974 } 975 } 976 else if( arg.startsWith( "-upload=" ) ) { 977 upldFile = arg.substring( "-upload=".length() ); 978 if( StringUtil.isNull( upldFile ) ) { 979 System.err.println( arg + "指定した場合は、引数を設定してください。" ); 980 } 981 } 982 else if( arg.startsWith( "-errEx=" ) ) { 983 isEx = "true".equalsIgnoreCase( arg.substring( "-errEx=".length() ) ); 984 } 985 // 7.2.5.0 (2020/06/01) postRedirect(POST時に強制的にリダイレクト) 986 else if( arg.startsWith( "-postRedirect=" ) ) { 987 postRedirect = "true".equalsIgnoreCase( arg.substring( "-postRedirect=".length() ) ); 988 } 989 else if( arg.startsWith( "-debug=" ) ) { 990 isDebug = "true".equalsIgnoreCase( arg.substring( "-debug=".length() ) ); 991 } 992 else if( arg.startsWith( "-usePost=" ) ) { 993 isPost = "true".equalsIgnoreCase( arg.substring( "-usePost=".length() ) ); 994 } 995 else if( StringUtil.startsChar( arg , '-' ) ) { // 引数が未定義(処理は継続させます。) 996 System.err.println( "Error Argment:" + arg ); 997 } 998 else if( StringUtil.startsChar( arg , '#' ) ) { // 引数がコメント 999 continue; 1000 } 1001 else { 1002 urlStr = arg; 1003 } 1004 } 1005 1006 try { // try catch を入れます。 1007 final HttpConnect conn = new HttpConnect( urlStr,userPass ); 1008 conn.usePost( isPost ); 1009 conn.setDebug( isDebug ); // 最初に入れておけば、それ以降、有効になります。 1010 1011 for( int i=0; i<paramKey.size(); i++ ) { 1012 conn.addRequestProperty( paramKey.get(i) , paramVal.get(i) ); 1013 } 1014 1015 for( int i=0; i<headerKey.size(); i++ ) { 1016 conn.addHeaderProperty( headerKey.get(i) , headerVal.get(i) ); 1017 } 1018 1019 // 6.8.1.3 (2017/08/04) proxy の設定 1020 if( !StringUtil.isNull( proxy ) ) { 1021 final String[] prm = StringUtil.csv2Array( proxy , ':' , 2 ); 1022 final String host = prm[0]; 1023 final int port = Integer.parseInt( prm[1] ); 1024 conn.setProxy( host , port ); 1025 } 1026 1027 conn.setCharset( encode ); // encode 指定 1028 conn.setTimeout( timeout ); // timeout属性追加 1029 conn.setUploadFile( upldFile ); 1030 conn.setDownloadFile( dwldFile ); 1031 conn.setPostRedirect( postRedirect ); // 7.2.5.0 (2020/06/01) 1032 1033 final String outData = conn.readData(); // 8.0.0.0 (2021/08/20) テスト用 1034 1035 try( PrintWriter writer = StringUtil.isNull( outFile ) 1036 ? FileUtil.getLogWriter( "System.out" ) 1037 : FileUtil.getPrintWriter( new File( outFile ),encode ) ) { 1038 if( !nonWriter ) { 1039 writer.println( outData ); 1040 } 1041 final int code = conn.getCode(); 1042 1043 // isEx=trueの場合、レスポンスコードが、4XX,5XX の時に RuntimeException を投げます 1044 if( code >= 400 ) { 1045 final String errMsg = conn.getMessage(); 1046 writer.println( errMsg ); 1047 if( isEx ) { 1048 throw new OgRuntimeException( errMsg ); 1049 } 1050 else { 1051 System.exit( code ); 1052 } 1053 } 1054 } 1055 } 1056 catch( final Throwable th ) { 1057 throw new OgRuntimeException( th ); 1058 } 1059 } 1060}