-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #46 from landy8530/master
Sync the functionality to 1.x version
- Loading branch information
Showing
14 changed files
with
533 additions
and
202 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
299 changes: 299 additions & 0 deletions
299
commons-core/src/main/java/org/fortune/commons/core/http/HttpClientHelper.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,299 @@ | ||
package org.fortune.commons.core.http; | ||
|
||
import org.apache.commons.lang3.StringUtils; | ||
import org.apache.http.*; | ||
import org.apache.http.client.config.RequestConfig; | ||
import org.apache.http.client.entity.UrlEncodedFormEntity; | ||
import org.apache.http.client.methods.CloseableHttpResponse; | ||
import org.apache.http.client.methods.HttpPost; | ||
import org.apache.http.client.methods.HttpRequestBase; | ||
import org.apache.http.entity.ContentType; | ||
import org.apache.http.entity.StringEntity; | ||
import org.apache.http.entity.mime.HttpMultipartMode; | ||
import org.apache.http.entity.mime.MultipartEntityBuilder; | ||
import org.apache.http.entity.mime.content.ByteArrayBody; | ||
import org.apache.http.entity.mime.content.ContentBody; | ||
import org.apache.http.entity.mime.content.FileBody; | ||
import org.apache.http.entity.mime.content.StringBody; | ||
import org.apache.http.impl.client.CloseableHttpClient; | ||
import org.apache.http.impl.client.HttpClients; | ||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; | ||
import org.apache.http.message.BasicHeader; | ||
import org.apache.http.message.BasicNameValuePair; | ||
import org.apache.http.util.CharsetUtils; | ||
import org.apache.http.util.EntityUtils; | ||
import org.fortune.commons.core.util.JsonUtil; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import java.io.File; | ||
import java.io.IOException; | ||
import java.util.*; | ||
|
||
/** | ||
* @author landyl | ||
* @create 9:54 08/23/2019 | ||
*/ | ||
public class HttpClientHelper { | ||
private static final Logger LOGGER = LoggerFactory.getLogger(HttpClientHelper.class); | ||
|
||
private CloseableHttpClient client; | ||
private List<NameValuePair> nameValuePostBodies; | ||
private List<Header> headers; | ||
private String mimeType; | ||
private Map<String, String> bodyParams; | ||
//Used to Multiple part form data | ||
private Map<String, ContentBody> contentBodies; | ||
|
||
|
||
public HttpClientHelper(RequestConfig requestConfig, List<NameValuePair> nameValuePostBodies, List<Header> headers, String mimeType, Map<String, String> bodyParams, Map<String, ContentBody> contentBodies) { | ||
PoolingHttpClientConnectionManager connectionManager = HttpClientManager.getConnManager(); | ||
if(requestConfig != null) { | ||
this.client = HttpClients.custom().setDefaultRequestConfig(requestConfig).setConnectionManager(connectionManager).build(); | ||
} else { | ||
this.client = HttpClients.custom().setConnectionManager(connectionManager).build(); | ||
} | ||
this.nameValuePostBodies = nameValuePostBodies; | ||
this.headers = headers; | ||
this.mimeType = mimeType; | ||
this.bodyParams = bodyParams; | ||
this.contentBodies = contentBodies; | ||
} | ||
|
||
public HttpResponseContent doPost(String url) { | ||
try { | ||
return this.doPost(url, HttpConstants.ENCODING_UTF8); | ||
} catch (Exception ex) { | ||
LOGGER.error("occurs an unexpected exception,url:{}", url, ex); | ||
return null; | ||
} | ||
} | ||
|
||
public HttpResponseContent doPost(String url, String urlEncoding) throws HttpException, IOException { | ||
HttpRequestBase request = null; | ||
CloseableHttpResponse response = null; | ||
|
||
if(StringUtils.isBlank(urlEncoding)) urlEncoding = HttpConstants.ENCODING_UTF8; | ||
|
||
try { | ||
HttpPost httpPost = new HttpPost(url); | ||
//set bodies | ||
if(ContentType.APPLICATION_FORM_URLENCODED.getMimeType().equals(mimeType)) { | ||
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePostBodies, urlEncoding)); | ||
} else if(ContentType.APPLICATION_JSON.getMimeType().equals(mimeType)){ | ||
String bodyParamsJson = JsonUtil.toJSONString(bodyParams); | ||
StringEntity stringEntity = new StringEntity(bodyParamsJson, ContentType.create(ContentType.APPLICATION_JSON.getMimeType(), urlEncoding)); | ||
httpPost.setEntity(stringEntity); | ||
} else if(ContentType.MULTIPART_FORM_DATA.getMimeType().equals(mimeType)){ | ||
MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create(); | ||
entityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); | ||
//file content body | ||
Iterator it = this.contentBodies.entrySet().iterator(); | ||
|
||
while(it.hasNext()) { | ||
Map.Entry<String, ContentBody> item = (Map.Entry)it.next(); | ||
entityBuilder.addPart(item.getKey(), item.getValue()); | ||
} | ||
|
||
//another body parameters | ||
Iterator<NameValuePair> nameValuePairIterator = this.nameValuePostBodies.iterator(); | ||
while(nameValuePairIterator.hasNext()) { | ||
NameValuePair nameValuePair = nameValuePairIterator.next(); | ||
entityBuilder.addPart(nameValuePair.getName(), new StringBody(nameValuePair.getValue(), ContentType.create(ContentType.TEXT_PLAIN.getMimeType(), urlEncoding))); | ||
} | ||
entityBuilder.setCharset(CharsetUtils.get(urlEncoding)); | ||
httpPost.setEntity(entityBuilder.build()); | ||
} else { | ||
throw new HttpException("Currently, we do not support the mine type equals to {} " + mimeType); | ||
} | ||
|
||
//set headers | ||
for (Header header : headers) { | ||
httpPost.setHeader(header); | ||
} | ||
request = httpPost; | ||
response = this.client.execute(httpPost); | ||
HttpResponseContent responseContent = this.buildResponseContent(response); | ||
return responseContent; | ||
} finally { | ||
this.close(request, response); | ||
} | ||
} | ||
|
||
public CloseableHttpClient getClient() { | ||
return this.client; | ||
} | ||
|
||
private HttpResponseContent buildResponseContent(CloseableHttpResponse response) throws HttpException, IOException { | ||
HttpResponseContent responseContent = new HttpResponseContent(); | ||
StatusLine statusLine = response.getStatusLine(); | ||
HttpEntity entity = response.getEntity(); | ||
try { | ||
Header enHeader = entity.getContentEncoding(); | ||
if (enHeader != null) { | ||
String encoding = enHeader.getValue().toLowerCase(); | ||
responseContent.setEncoding(encoding); | ||
} | ||
|
||
String contentType = this.getResponseContentType(entity); | ||
int statusCode = statusLine.getStatusCode(); | ||
if (statusCode != HttpStatus.SC_OK) { | ||
String result = EntityUtils.toString(response.getEntity(), HttpConstants.ENCODING_UTF8); | ||
throw new HttpException("Invalid status code: " + statusCode + ", result: " + result); | ||
} | ||
|
||
responseContent.setStatusCode(statusCode); | ||
responseContent.setContentType(contentType); | ||
responseContent.setContentTypeString(this.getResponseContentTypeString(entity)); | ||
responseContent.setContentBytes(EntityUtils.toByteArray(entity)); | ||
} finally { | ||
if (entity != null) { | ||
entity.getContent().close(); | ||
} | ||
} | ||
return responseContent; | ||
} | ||
|
||
|
||
private String getResponseContentType(HttpEntity method) { | ||
Header contentType = method.getContentType(); | ||
if (contentType == null) { | ||
return null; | ||
} else { | ||
String ret = null; | ||
|
||
try { | ||
HeaderElement[] hes = contentType.getElements(); | ||
if (hes != null && hes.length > 0) { | ||
ret = hes[0].getName(); | ||
} | ||
} catch (Exception var5) { | ||
} | ||
|
||
return ret; | ||
} | ||
} | ||
|
||
private String getResponseContentTypeString(HttpEntity method) { | ||
Header contentType = method.getContentType(); | ||
return contentType == null ? null : contentType.getValue(); | ||
} | ||
|
||
private void close(HttpRequestBase request, CloseableHttpResponse response) throws IOException { | ||
if (request != null) { | ||
request.releaseConnection(); | ||
} | ||
if (response != null) { | ||
response.close(); | ||
} | ||
} | ||
|
||
public static class Builder { | ||
private List<NameValuePair> nameValuePostBodies = new LinkedList(); | ||
private List<Header> headers = new LinkedList(); | ||
private RequestConfig requestConfig; | ||
|
||
private Integer socketTimeout = 60000; | ||
private Integer connectTimeout = 60000; | ||
private Integer connectionRequestTimeout = 60000; | ||
|
||
private String mimeType; | ||
private Map<String, String> bodyParamsCopy; | ||
//Used to Multiple part form data | ||
private Map<String, ContentBody> contentBodies; | ||
|
||
public Builder() { | ||
contentBodies = new LinkedHashMap<>(); | ||
} | ||
|
||
public Builder(Integer socketTimeout, Integer connectTimeout, Integer connectionRequestTimeout) { | ||
this(); | ||
this.socketTimeout = socketTimeout; | ||
this.connectTimeout = connectTimeout; | ||
this.connectionRequestTimeout = connectionRequestTimeout; | ||
} | ||
|
||
public Builder setBodyParams(Map<String, String> bodyParams) { | ||
bodyParamsCopy = bodyParams; | ||
if (bodyParams != null && !bodyParams.isEmpty()) { | ||
for (Map.Entry<String, String> entry : bodyParams.entrySet()) { | ||
nameValuePostBodies.add(new BasicNameValuePair(entry.getKey(), entry.getValue())); | ||
} | ||
} | ||
return this; | ||
} | ||
|
||
public Builder setBodyParams(String name, String value) { | ||
BasicNameValuePair nvp = new BasicNameValuePair(name, value); | ||
this.nameValuePostBodies.add(nvp); | ||
if(this.bodyParamsCopy == null) { | ||
this.bodyParamsCopy = new HashMap<>(); | ||
} | ||
this.bodyParamsCopy.put(name, value); | ||
return this; | ||
} | ||
|
||
public Builder setHeaderParams(Map<String, String> headerParams) { | ||
if(headerParams.containsKey(HttpConstants.CONTENT_TYPE)) { | ||
mimeType = headerParams.get(HttpConstants.CONTENT_TYPE); | ||
} | ||
if (headerParams != null && !headerParams.isEmpty()) { | ||
for (Map.Entry<String, String> entry : headerParams.entrySet()) { | ||
//https://github.com/landy8530/fortune-commons/issues/44 | ||
if(!isMultiplePart(mimeType)) { | ||
headers.add(new BasicHeader(entry.getKey(), entry.getValue())); | ||
} | ||
} | ||
} | ||
return this; | ||
} | ||
|
||
public Builder setMimeType(String mimeType) { | ||
this.mimeType = mimeType; | ||
//https://github.com/landy8530/fortune-commons/issues/44 | ||
if(!isMultiplePart(mimeType)) { | ||
headers.add(new BasicHeader(HttpConstants.CONTENT_TYPE, mimeType)); | ||
} | ||
return this; | ||
} | ||
|
||
public Builder setRequestConfig(RequestConfig requestConfig) { | ||
this.requestConfig = requestConfig; | ||
return this; | ||
} | ||
|
||
public Builder setRequestConfig(Integer socketTimeout, Integer connectTimeout, Integer connectionRequestTimeout) { | ||
this.requestConfig = RequestConfig.custom().setConnectionRequestTimeout(connectionRequestTimeout).setConnectTimeout(connectTimeout).setSocketTimeout(socketTimeout).build(); | ||
return this; | ||
} | ||
|
||
public Builder addContent(String fileDataKey, File file) { | ||
FileBody fileBody = new FileBody(file); | ||
this.contentBodies.put(fileDataKey, fileBody); | ||
return this; | ||
} | ||
|
||
public Builder addContent(String fileDataKey, byte[] content) { | ||
ByteArrayBody byteArrayBody = new ByteArrayBody(content, fileDataKey); | ||
this.contentBodies.put(fileDataKey, byteArrayBody); | ||
return this; | ||
} | ||
|
||
public Builder addContentBodies(Map<String, ContentBody> contentBodies) { | ||
this.contentBodies.putAll(contentBodies); | ||
return this; | ||
} | ||
|
||
private boolean isMultiplePart(String mimeType) { | ||
return ContentType.MULTIPART_FORM_DATA.getMimeType().equals(mimeType); | ||
} | ||
|
||
public HttpClientHelper build() { | ||
if(this.requestConfig == null) { | ||
this.setRequestConfig(socketTimeout, connectTimeout, connectionRequestTimeout); | ||
} | ||
if(StringUtils.isBlank(mimeType)) mimeType = ContentType.APPLICATION_JSON.getMimeType(); | ||
return new HttpClientHelper(requestConfig, nameValuePostBodies, headers, mimeType, bodyParamsCopy , contentBodies); | ||
} | ||
} | ||
} |
56 changes: 56 additions & 0 deletions
56
commons-core/src/main/java/org/fortune/commons/core/http/HttpClientManager.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package org.fortune.commons.core.http; | ||
|
||
import org.apache.http.Consts; | ||
import org.apache.http.config.*; | ||
import org.apache.http.conn.socket.ConnectionSocketFactory; | ||
import org.apache.http.conn.socket.PlainConnectionSocketFactory; | ||
import org.apache.http.conn.ssl.SSLConnectionSocketFactory; | ||
import org.apache.http.ssl.SSLContextBuilder; | ||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import javax.net.ssl.SSLContext; | ||
import java.nio.charset.CodingErrorAction; | ||
|
||
/** | ||
* @author landyl | ||
* @create 10:10 08/23/2019 | ||
*/ | ||
class HttpClientManager { | ||
private static final Logger LOGGER = LoggerFactory.getLogger(HttpClientManager.class); | ||
|
||
private static PoolingHttpClientConnectionManager connManager = null; | ||
|
||
static { | ||
try { | ||
// setup a Trust Strategy that allows all certificates. | ||
SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, (arg0, arg1) -> true).build(); | ||
// here's the special part: | ||
// -- need to create an SSL Socket Factory, to use our weakened "trust strategy"; | ||
// -- and create a Registry, to register it. | ||
// | ||
RegistryBuilder<ConnectionSocketFactory> builder = RegistryBuilder.create(); | ||
builder.register("http", PlainConnectionSocketFactory.INSTANCE) | ||
.register("https", new SSLConnectionSocketFactory(sslContext)); | ||
|
||
Registry<ConnectionSocketFactory> socketFactoryRegistry = builder.build(); | ||
// now, we create connection-manager using our Registry. | ||
// -- allows multi-threaded use | ||
connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry); | ||
SocketConfig socketConfig = SocketConfig.custom().setTcpNoDelay(true).build(); | ||
connManager.setDefaultSocketConfig(socketConfig); | ||
MessageConstraints messageConstraints = MessageConstraints.custom().setMaxHeaderCount(200).setMaxLineLength(2000).build(); | ||
ConnectionConfig connectionConfig = ConnectionConfig.custom().setMalformedInputAction(CodingErrorAction.IGNORE).setUnmappableInputAction(CodingErrorAction.IGNORE).setCharset(Consts.UTF_8).setMessageConstraints(messageConstraints).build(); | ||
connManager.setDefaultConnectionConfig(connectionConfig); | ||
connManager.setMaxTotal(200); | ||
connManager.setDefaultMaxPerRoute(20); | ||
} catch (Exception ex) { | ||
LOGGER.error("occurs an unexpected exception: ",ex); | ||
} | ||
} | ||
|
||
public static PoolingHttpClientConnectionManager getConnManager() { | ||
return connManager; | ||
} | ||
} |
Oops, something went wrong.