001/** 002 * Copyright (c) 2015-2022, Michael Yang 杨福海 (fuhai999@gmail.com). 003 * <p> 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 * <p> 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * <p> 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, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package io.jboot.components.http; 017 018import io.jboot.utils.StrUtil; 019 020import javax.net.ssl.SSLContext; 021import java.io.File; 022import java.io.FileInputStream; 023import java.io.FileNotFoundException; 024import java.io.InputStream; 025import java.net.Proxy; 026import java.util.LinkedHashMap; 027import java.util.Map; 028 029/** 030 * httpRequest 031 */ 032public class JbootHttpRequest { 033 034 public static final String METHOD_GET = "GET"; 035 public static final String METHOD_POST = "POST"; 036 037 public static final String METHOD_HEAD = "HEAD"; 038 public static final String METHOD_OPTIONS = "OPTIONS"; 039 public static final String METHOD_PUT = "PUT"; 040 public static final String METHOD_PATCH = "PATCH"; 041 public static final String METHOD_DELETE = "DELETE"; 042 public static final String METHOD_TRACE = "TRACE"; 043 044 public static final int READ_TIME_OUT = 1000 * 10; // 10秒 045 public static final int CONNECT_TIME_OUT = 1000 * 5; // 5秒 046 public static final String CHAR_SET = "UTF-8"; 047 048 public static final String CONTENT_TYPE_TEXT = "text/plain; charset=utf-8"; 049 public static final String CONTENT_TYPE_JSON = "application/json; charset=utf-8"; 050 public static final String CONTENT_TYPE_URL_ENCODED = "application/x-www-form-urlencoded; charset=utf-8"; 051 052 private String requestUrl; 053 054 private Map<String, String> headers; 055 private Map<String, Object> params; 056 057 058 private String method = METHOD_GET; 059 private String charset = CHAR_SET; 060 061 private boolean multipartFormData = false; 062 063 private String certPath; 064 private String certPass; 065 066 private int readTimeOut; 067 private int connectTimeOut; 068 private String contentType; 069 070 071 private File downloadFile; 072 private String bodyContent; 073 074 // 如果某些时候只是为了去读取 http 头信息,而不需要 http body,可以配置为 false 075 private boolean readBody = true; 076 077 // 遇到重定向是否自动跟随 078 private boolean instanceFollowRedirects = false; 079 080 // 自定义 sslContext 081 private SSLContext sslContext; 082 083 // 自定义 http 代理 084 private HttpProxyInfo httpProxyInfo; 085 086 // 是否自动重定向(手动实现的,而非) 087 private boolean autoRedirect = true; 088 089 // 最大的重定向次数 090 private int maxRedirectCount = 3; 091 092 // 当前的重定向次数 093 private int currentRedirectCount = 0; 094 095 096 public static JbootHttpRequest create(String url) { 097 return new JbootHttpRequest(url); 098 } 099 100 public static JbootHttpRequest create(String url, String method) { 101 JbootHttpRequest request = new JbootHttpRequest(url); 102 request.setMethod(method); 103 return request; 104 } 105 106 public static JbootHttpRequest create(String url, Map<String, Object> params) { 107 JbootHttpRequest request = new JbootHttpRequest(url); 108 request.setParams(params); 109 return request; 110 } 111 112 public static JbootHttpRequest create(String url, Map<String, Object> params, String method) { 113 JbootHttpRequest request = new JbootHttpRequest(url); 114 request.setMethod(method); 115 request.setParams(params); 116 return request; 117 } 118 119 public JbootHttpRequest() { 120 JbootHttpConfig config = JbootHttpManager.me().getHttpConfig(); 121 122 if (StrUtil.isNotBlank(config.getCertPath())) { 123 this.certPath = config.getCertPath(); 124 } 125 if (StrUtil.isNotBlank(config.getCertPass())) { 126 this.certPass = config.getCertPass(); 127 } 128 129 this.readTimeOut = config.getReadTimeOut(); 130 this.connectTimeOut = config.getConnectTimeOut(); 131 this.contentType = config.getContentType(); 132 this.httpProxyInfo = config.getHttpProxyInfo(); 133 } 134 135 public JbootHttpRequest(String url) { 136 this(); 137 this.requestUrl = url; 138 } 139 140 141 public void addParam(String key, Object value) { 142 if (params == null) { 143 params = new LinkedHashMap<>(); 144 } 145 if (value instanceof File) { 146 setMultipartFormData(true); 147 } 148 params.put(key, value); 149 } 150 151 public void addParams(Map<String, Object> map) { 152 if (params == null) { 153 params = new LinkedHashMap<>(); 154 } 155 for (Map.Entry<String, Object> entry : map.entrySet()) { 156 if (entry.getValue() == null) { 157 continue; 158 } 159 if (entry.getValue() instanceof File) { 160 setMultipartFormData(true); 161 } 162 163 params.put(entry.getKey(), entry.getValue()); 164 } 165 } 166 167 public void setRequestUrl(String requestUrl) { 168 this.requestUrl = requestUrl; 169 } 170 171 public String getCertPath() { 172 return certPath; 173 } 174 175 public InputStream getCertInputStream() throws FileNotFoundException { 176 if (StrUtil.isBlank(certPath)) { 177 return null; 178 } 179 180 if (certPath.toLowerCase().startsWith("classpath:")) { 181 182 String path = certPath.substring(10).trim(); 183 InputStream inStream = getClassLoader().getResourceAsStream(path); 184 185 if (inStream == null) { 186 inStream = getClassLoader().getResourceAsStream("webapp/" + path); 187 } 188 189 if (inStream == null) { 190 throw new FileNotFoundException("Can not load resource: " + path + " in classpath."); 191 } else { 192 return inStream; 193 } 194 } else { 195 return new FileInputStream(certPath); 196 } 197 } 198 199 private ClassLoader getClassLoader() { 200 ClassLoader ret = Thread.currentThread().getContextClassLoader(); 201 return ret != null ? ret : getClass().getClassLoader(); 202 } 203 204 public void setCertPath(String certPath) { 205 this.certPath = certPath; 206 } 207 208 public String getCertPass() { 209 return certPass; 210 } 211 212 public void setCertPass(String certPass) { 213 this.certPass = certPass; 214 } 215 216 public String getMethod() { 217 return method; 218 } 219 220 public void setMethod(String method) { 221 this.method = method; 222 } 223 224 225 public int getReadTimeOut() { 226 return readTimeOut; 227 } 228 229 public void setReadTimeOut(int readTimeOut) { 230 this.readTimeOut = readTimeOut; 231 } 232 233 public int getConnectTimeOut() { 234 return connectTimeOut; 235 } 236 237 public void setConnectTimeOut(int connectTimeOut) { 238 this.connectTimeOut = connectTimeOut; 239 } 240 241 public String getRequestUrl() { 242 return requestUrl; 243 } 244 245 public Map<String, String> getHeaders() { 246 return headers; 247 } 248 249 public String getHeader(String name){ 250 return headers != null ? headers.get(name) : null; 251 } 252 253 public void setHeaders(Map<String, String> headers) { 254 this.headers = headers; 255 } 256 257 public void addHeader(String key, String value) { 258 if (headers == null) { 259 headers = new LinkedHashMap<>(); 260 } 261 headers.put(key, value); 262 } 263 264 public void addHeaders(Map<String, String> headers) { 265 if (headers == null || headers.isEmpty()) { 266 return; 267 } 268 269 if (this.headers == null) { 270 this.headers = new LinkedHashMap<>(); 271 } 272 this.headers.putAll(headers); 273 } 274 275 public Map<String, Object> getParams() { 276 return params; 277 } 278 279 public void setParams(Map<String, Object> params) { 280 if (params == null) { 281 return; 282 } 283 for (Map.Entry<String, Object> entry : params.entrySet()) { 284 if (entry.getValue() == null) { 285 continue; 286 } 287 if (entry.getValue() instanceof File) { 288 setMultipartFormData(true); 289 } 290 } 291 this.params = params; 292 } 293 294 public boolean isPostRequest() { 295 return METHOD_POST.equalsIgnoreCase(method); 296 } 297 298 public boolean isPutRequest() { 299 return METHOD_PUT.equalsIgnoreCase(method); 300 } 301 302 public boolean isPostOrPutRequest() { 303 return isPostRequest() || isPutRequest(); 304 } 305 306 public String getCharset() { 307 return charset; 308 } 309 310 public void setCharset(String charset) { 311 this.charset = charset; 312 } 313 314 public boolean isMultipartFormData() { 315 return multipartFormData; 316 } 317 318 public void setMultipartFormData(boolean multipartFormData) { 319 this.multipartFormData = multipartFormData; 320 } 321 322 public File getDownloadFile() { 323 return downloadFile; 324 } 325 326 public void setDownloadFile(File downloadFile) { 327 this.downloadFile = downloadFile; 328 } 329 330 public String getContentType() { 331 return contentType; 332 } 333 334 public void setContentType(String contentType) { 335 this.contentType = contentType; 336 } 337 338 339 public String getBodyContent() { 340 return bodyContent; 341 } 342 343 public String getUploadBodyString() { 344 if (bodyContent != null) { 345 return bodyContent; 346 } else { 347 return buildParams(); 348 } 349 } 350 351 public void setBodyContent(String bodyContent) { 352 this.bodyContent = bodyContent; 353 } 354 355 356 private String buildParams() { 357 return StrUtil.mapToQueryString(getParams()); 358 } 359 360 361 public void appendParasToUrl() { 362 String params = buildParams(); 363 364 if (StrUtil.isBlank(params)) { 365 return; 366 } 367 368 String originUrl = getRequestUrl(); 369 if (originUrl.contains("?")) { 370 originUrl = originUrl + "&" + params; 371 } else { 372 originUrl = originUrl + "?" + params; 373 } 374 375 setRequestUrl(originUrl); 376 } 377 378 379 public boolean isHttps() { 380 return requestUrl != null && requestUrl.toLowerCase().startsWith("https"); 381 } 382 383 public boolean isReadBody() { 384 return readBody; 385 } 386 387 public void setReadBody(boolean readBody) { 388 this.readBody = readBody; 389 } 390 391 public boolean isInstanceFollowRedirects() { 392 return instanceFollowRedirects; 393 } 394 395 public void setInstanceFollowRedirects(boolean instanceFollowRedirects) { 396 this.instanceFollowRedirects = instanceFollowRedirects; 397 } 398 399 public SSLContext getSslContext() { 400 return sslContext; 401 } 402 403 public void setSslContext(SSLContext sslContext) { 404 this.sslContext = sslContext; 405 } 406 407 public HttpProxyInfo getHttpProxyInfo() { 408 return httpProxyInfo; 409 } 410 411 public void setHttpProxyInfo(HttpProxyInfo httpProxyInfo) { 412 this.httpProxyInfo = httpProxyInfo; 413 } 414 415 public Proxy getProxy() { 416 return httpProxyInfo != null ? httpProxyInfo.getProxy() : null; 417 } 418 419 public boolean isAutoRedirect() { 420 return autoRedirect; 421 } 422 423 public void setAutoRedirect(boolean autoRedirect) { 424 this.autoRedirect = autoRedirect; 425 } 426 427 public int getMaxRedirectCount() { 428 return maxRedirectCount; 429 } 430 431 public void setMaxRedirectCount(int maxRedirectCount) { 432 this.maxRedirectCount = maxRedirectCount; 433 } 434 435 public int getCurrentRedirectCount() { 436 return currentRedirectCount; 437 } 438 439 public void setCurrentRedirectCount(int currentRedirectCount) { 440 this.currentRedirectCount = currentRedirectCount; 441 } 442}