Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.alogic.remote.httpclient.HttpClientRequest Maven / Gradle / Ivy
package com.alogic.remote.httpclient;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.net.URI;
import java.nio.charset.Charset;
import com.alogic.remote.util.RemoteCallMetrics;
import com.alogic.tracer.Tool;
import com.alogic.tracer.TraceContext;
import com.anysoft.rrm.RRData;
import com.anysoft.rrm.RRDataHandlerFactory;
import org.apache.http.*;
import org.apache.http.client.entity.GzipCompressingEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.entity.*;
import org.apache.http.impl.client.CloseableHttpClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import com.alogic.remote.Request;
import com.alogic.remote.Response;
import com.alogic.remote.backend.Backend;
import com.alogic.rpc.CallException;
import com.anysoft.util.Properties;
import com.anysoft.stream.Handler;
/**
* Request
*
* @author yyduan
* @since 1.6.8.12
*
* @version 1.6.8.14
* - 优化http远程调用的超时机制
*
* @version 1.6.8.15 [20170511 duanyy]
* - 增加绝对路径调用功能
*
* @version 1.6.10.1 [20170910 duanyy]
* - 修正httpclient连接的“failed to respond”异常;
*
* @version 1.6.10.6 [20171114 duanyy]
* - 增加Filter的事件触发
*
* @version 1.6.10.9 [20171124 duanyy]
* - 增加{@link #getPathInfo()}和{@link #getQueryInfo()}方法
*
* @version 1.6.11.14 [duanyy 20180129]
* - 修正QueryInfo和服务器取法不一致的问题
*
* @version 1.6.13.6 [20200629 duanyy]
* - 增加rpc的debug信息的输出;
*
* @version 1.6.13.21 [20201021 duanyy]
* - 优化代码结构
* - 支持gzip压缩
*/
public class HttpClientRequest implements Request{
protected static final Logger LOG = LoggerFactory.getLogger(HttpClientRequest.class);
protected HttpRequestBase httpRequest = null;
protected CloseableHttpClient httpClient = null;
protected HttpClient client = null;
protected HttpClientConfig clientConfig = null;
protected boolean debug = false;
public HttpClientRequest(String method,CloseableHttpClient httpClient,HttpClient client,HttpClientConfig clientConfig,boolean debug){
this.httpClient = httpClient;
this.client = client;
this.clientConfig = clientConfig;
this.debug = clientConfig.isDebug() | debug;
httpRequest = getRequestByMethod(method);
if (httpRequest == null){
httpRequest = new HttpPost();
}
httpRequest.setConfig(clientConfig.getRequestConfig());
}
public HttpRequestBase getRequestByMethod(final String method){
HttpClient.Method m = HttpClient.Method.valueOf(method.toUpperCase());
return m.createRequest();
}
/**
* 获取当前的URI
* @return URI
*/
public String getURI(){
URI uri = this.httpRequest != null ? this.httpRequest.getURI() : null;
return uri != null ? uri.toString() : "";
}
public String getPathInfo(){
URI uri = this.httpRequest != null ? this.httpRequest.getURI() : null;
return uri != null ? uri.getPath() : "";
}
public String getQueryInfo(){
URI uri = this.httpRequest != null ? this.httpRequest.getURI() : null;
return uri != null ? uri.getRawQuery() : "";
}
/**
* 获取指定的header值
* @param name header名称
* @param dft 缺省值
* @return header值
*/
public String getHeader(String name,String dft){
Header header = this.httpRequest != null ? this.httpRequest.getFirstHeader(name) : null;
return header == null ? dft: header.getValue();
}
@Override
public Request setHeader(String name, String value) {
if (this.httpRequest != null){
this.httpRequest.setHeader(name, value);
}
return this;
}
@Override
public Request setBody(String text) {
if (httpRequest != null && httpRequest instanceof HttpEntityEnclosingRequestBase){
HttpEntityEnclosingRequestBase entityRequest = (HttpEntityEnclosingRequestBase) httpRequest;
HttpEntity entity = new StringEntity(text,clientConfig.getEncoding());
if (clientConfig.isGzipEnable()){
entity = new GzipCompressingEntity(entity);
}
entityRequest.setEntity(entity);
}
return this;
}
@Override
public Request setBody(byte[] body) {
if (httpRequest != null && httpRequest instanceof HttpEntityEnclosingRequestBase){
HttpEntityEnclosingRequestBase entityRequest = (HttpEntityEnclosingRequestBase) httpRequest;
HttpEntity entity = new ByteArrayEntity(body);
if (clientConfig.isGzipEnable()){
entity = new GzipCompressingEntity(entity);
}
entityRequest.setEntity(entity);
}
return this;
}
@Override
public Request setBody(InputStream in) {
if (httpRequest != null && httpRequest instanceof HttpEntityEnclosingRequestBase){
HttpEntityEnclosingRequestBase entityRequest = (HttpEntityEnclosingRequestBase) httpRequest;
HttpEntity entity = new InputStreamEntity(in);
if (clientConfig.isGzipEnable()){
entity = new GzipCompressingEntity(entity);
}
entityRequest.setEntity(entity);
}
return this;
}
@Override
public Request setMultipartBody(String formKey, String filename, String content) {
if (httpRequest != null && httpRequest instanceof HttpEntityEnclosingRequestBase){
HttpEntityEnclosingRequestBase entityRequest = (HttpEntityEnclosingRequestBase) httpRequest;
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setCharset(Charset.forName(clientConfig.getEncoding()));
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.addBinaryBody(formKey, content.getBytes(), ContentType.MULTIPART_FORM_DATA, filename);
entityRequest.setEntity(builder.build());
}
return this;
}
@Override
public Request setMultipartBody(String formKey, String filename, byte[] content) {
if (httpRequest != null && httpRequest instanceof HttpEntityEnclosingRequestBase){
HttpEntityEnclosingRequestBase entityRequest = (HttpEntityEnclosingRequestBase) httpRequest;
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setCharset(Charset.forName(clientConfig.getEncoding()));
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.addBinaryBody(formKey,content, ContentType.MULTIPART_FORM_DATA, filename);
entityRequest.setEntity(builder.build());
}
return this;
}
@Override
public Request setMultipartBody(String formKey, String filename, InputStream in) {
if (httpRequest != null && httpRequest instanceof HttpEntityEnclosingRequestBase){
HttpEntityEnclosingRequestBase entityRequest = (HttpEntityEnclosingRequestBase) httpRequest;
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setCharset(Charset.forName(clientConfig.getEncoding()));
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.addBinaryBody(formKey, in, ContentType.MULTIPART_FORM_DATA, filename);
entityRequest.setEntity(builder.build());
}
return this;
}
@Override
public Request setBody(DirectOutput out){
if (httpRequest != null && httpRequest instanceof HttpEntityEnclosingRequestBase){
HttpEntityEnclosingRequestBase entityRequest = (HttpEntityEnclosingRequestBase) httpRequest;
HttpEntity entity = new DirectOutputEntity(out);
if (clientConfig.isGzipEnable()){
entity = new GzipCompressingEntity(entity);
}
entityRequest.setEntity(entity);
}
return this;
}
@Override
public Response execute(String path,String key,Properties ctx) {
int retryCount = 0;
int autoRetry = 0;
Response result = null;
String lastErrorCode = "core.io_error";
String lastErrorMsg = "";
while (true){
Backend backend = null;
long start = System.nanoTime();
boolean error = false;
try {
backend = client.getBackend(key,ctx, autoRetry > 0 ? 0 : retryCount ++ );
if (backend != null){
result = execute(path,backend,path);
}
break;
}catch (CallException ex){
error = true;
lastErrorCode = ex.getCode();
lastErrorMsg = ex.getMessage();
if (lastErrorCode.equals("core.e1602")
|| lastErrorCode.equals("core.e1603")
|| lastErrorCode.equals("core.e1604")){
//对于internal错误,属于连接错误,可以重试
autoRetry = autoRetry >= clientConfig.getAutoRetryCnt() ? 0 : autoRetry + 1;
if (autoRetry > 0){
LOG.error("Internal error occurs,Retry " + autoRetry);
}
}else{
if (!lastErrorCode.startsWith("core")){
throw ex;
}
}
}finally{
if (backend != null){
backend.count(System.nanoTime() - start, error);
}
}
}
if (result == null){
throw new CallException(lastErrorCode,lastErrorMsg);
}
return result;
}
@Override
public Response execute(String fullPath) {
String url = fullPath;
long start = System.nanoTime();
boolean error = false;
String reason = "ok";
TraceContext tc = null;
if (clientConfig.isTraceEnable()){
tc = Tool.start();
}
try {
httpRequest.setURI(URI.create(url));
//request事件
client.onRequest(this);
TraceContext child = tc == null ? null:tc.newChild();
if (child != null){
httpRequest.setHeader(clientConfig.getTraceId(), child.sn());
httpRequest.setHeader(clientConfig.getTraceOrder(), child.order());
}
if (debug){
LOG.info(String.format("Request:%s",fullPath));
LOG.info("\tHeaders:");
HeaderIterator iter = httpRequest.headerIterator();
while (iter.hasNext()){
Header header = iter.nextHeader();
LOG.info(String.format("\t\t%s:%s",header.getName(),header.getValue()));
}
}
CloseableHttpResponse resp = httpClient.execute(httpRequest);
if (debug){
StatusLine status = resp.getStatusLine();
LOG.info(String.format("Response:%s-%s",status.getStatusCode(),status.getReasonPhrase()));
LOG.info("\tHeaders:");
HeaderIterator iter = resp.headerIterator();
while (iter.hasNext()){
Header header = iter.nextHeader();
LOG.info(String.format("\t\t%s:%s",header.getName(),header.getValue()));
}
}
HttpClientResponse response = new HttpClientResponse(resp,clientConfig.getEncoding());
//response事件
client.onResponse(response);
return response;
}catch (SocketTimeoutException ex){
error = true;
reason = ex.getMessage();
throw new CallException("core.e1601",url, ex);
}catch (ConnectTimeoutException ex){
error = true;
reason = ex.getMessage();
throw new CallException("core.e1602",url, ex);
}catch (ConnectException ex){
error = true;
reason = ex.getMessage();
throw new CallException("core.e1603",url, ex);
}catch (NoHttpResponseException ex){
error = true;
reason = ex.getMessage();
throw new CallException("core.e1604",url, ex);
}catch (Exception ex){
error = true;
reason = ex.getMessage();
throw new CallException("core.e1004",url, ex);
}finally{
if (clientConfig.isMetricsOutput()){
RemoteCallMetrics m = new RemoteCallMetrics(url);
m.count(System.nanoTime() - start,error);
Handler handler = RRDataHandlerFactory.getHandler();
if (handler != null){
handler.handle(m,System.currentTimeMillis());
}
}
if (clientConfig.isTraceEnable()){
Tool.end(tc, "Remote", url, error?"FAILED":"OK", reason);
}
}
}
@Override
public Response execute(String fullPath,String rpcId) {
String url = fullPath;
long start = System.nanoTime();
boolean error = false;
String reason = "ok";
TraceContext tc = null;
if (clientConfig.isTraceEnable()){
tc = Tool.start();
}
try {
httpRequest.setURI(URI.create(url));
//request事件
client.onRequest(this);
TraceContext child = tc == null ? null:tc.newChild();
if (child != null){
httpRequest.setHeader(clientConfig.getTraceId(), child.sn());
httpRequest.setHeader(clientConfig.getTraceOrder(), child.order());
}
if (debug){
LOG.info(String.format("Request:%s",fullPath));
LOG.info("\tHeaders:");
HeaderIterator iter = httpRequest.headerIterator();
while (iter.hasNext()){
Header header = iter.nextHeader();
LOG.info(String.format("\t\t%s:%s",header.getName(),header.getValue()));
}
}
CloseableHttpResponse resp = httpClient.execute(httpRequest);
if (debug){
StatusLine status = resp.getStatusLine();
LOG.info(String.format("Response:%s-%s",status.getStatusCode(),status.getReasonPhrase()));
LOG.info("\tHeaders:");
HeaderIterator iter = resp.headerIterator();
while (iter.hasNext()){
Header header = iter.nextHeader();
LOG.info(String.format("\t\t%s:%s",header.getName(),header.getValue()));
}
}
HttpClientResponse response = new HttpClientResponse(resp,clientConfig.getEncoding());
//response事件
client.onResponse(response);
return response;
}catch (SocketTimeoutException ex){
error = true;
reason = ex.getMessage();
throw new CallException("core.e1601",url, ex);
}catch (ConnectTimeoutException ex){
error = true;
reason = ex.getMessage();
throw new CallException("core.e1602",url, ex);
}catch (ConnectException ex){
error = true;
reason = ex.getMessage();
throw new CallException("core.e1603",url, ex);
}catch (NoHttpResponseException ex){
error = true;
reason = ex.getMessage();
throw new CallException("core.e1604",url, ex);
}catch (Exception ex){
error = true;
reason = ex.getMessage();
ex.printStackTrace();
throw new CallException("core.e1004",url, ex);
}finally{
if (clientConfig.isMetricsOutput()){
RemoteCallMetrics m = new RemoteCallMetrics(url,rpcId);
m.count(System.nanoTime() - start,error);
Handler handler = RRDataHandlerFactory.getHandler();
if (handler != null){
handler.handle(m,System.currentTimeMillis());
}
}
if (clientConfig.isTraceEnable()){
Tool.end(tc, "Remote", url, error?"FAILED":"OK", reason);
}
}
}
public String getMetricsId(String id){
return String.format("rpc.thpt:%s",id);
}
protected Response execute(String path,Backend backend,String rpcId) {
String url = client.getInvokeURL(backend, path);
long start = System.nanoTime();
boolean error = false;
String reason = "ok";
TraceContext tc = null;
if (clientConfig.isTraceEnable()){
tc = Tool.start();
}
try {
httpRequest.setURI(URI.create(url));
//request事件
client.onRequest(this);
TraceContext child = tc == null ? null:tc.newChild();
if (child != null){
httpRequest.setHeader(clientConfig.getTraceId(), child.sn());
httpRequest.setHeader(clientConfig.getTraceOrder(), child.order());
}
if (debug){
LOG.info(String.format("Request:%s",url));
LOG.info("\tHeaders:");
HeaderIterator iter = httpRequest.headerIterator();
while (iter.hasNext()){
Header header = iter.nextHeader();
LOG.info(String.format("\t\t%s:%s",header.getName(),header.getValue()));
}
}
CloseableHttpResponse resp = httpClient.execute(httpRequest);
if (debug){
StatusLine status = resp.getStatusLine();
LOG.info(String.format("Response:%s-%s",status.getStatusCode(),status.getReasonPhrase()));
LOG.info("\tHeaders:");
HeaderIterator iter = resp.headerIterator();
while (iter.hasNext()){
Header header = iter.nextHeader();
LOG.info(String.format("\t\t%s:%s",header.getName(),header.getValue()));
}
}
HttpClientResponse response = new HttpClientResponse(resp,clientConfig.getEncoding());
//response事件
client.onResponse(response);
return response;
}catch (SocketTimeoutException ex){
error = true;
reason = ex.getMessage();
throw new CallException("core.e1601",url, ex);
}catch (ConnectTimeoutException ex){
error = true;
reason = ex.getMessage();
throw new CallException("core.e1602",url, ex);
}catch (ConnectException ex){
error = true;
reason = ex.getMessage();
throw new CallException("core.e1603",url, ex);
}catch (NoHttpResponseException ex){
error = true;
reason = ex.getMessage();
throw new CallException("core.e1604",url, ex);
}catch (Exception ex){
error = true;
reason = ex.getMessage();
throw new CallException("core.e1004",url, ex);
}finally{
if (clientConfig.isMetricsOutput()){
RemoteCallMetrics m = new RemoteCallMetrics(url,rpcId);
m.count(System.nanoTime() - start,error);
Handler handler = RRDataHandlerFactory.getHandler();
if (handler != null){
handler.handle(m,System.currentTimeMillis());
}
}
if (clientConfig.isTraceEnable()){
Tool.end(tc, "Remote", url, error?"FAILED":"OK", reason);
}
}
}
@Override
public void close() {
if (httpRequest != null){
httpRequest.releaseConnection();
}
}
public static class DirectOutputEntity extends AbstractHttpEntity{
protected DirectOutput out = null;
public DirectOutputEntity(DirectOutput out){
this.out = out;
}
@Override
public boolean isRepeatable() {
return true;
}
@Override
public long getContentLength() {
// i don't know.
return -1;
}
@Override
public InputStream getContent() throws IOException,
UnsupportedOperationException {
throw new UnsupportedOperationException();
}
@Override
public void writeTo(OutputStream outstream) throws IOException {
if (this.out != null){
this.out.writeTo(outstream);
}
}
@Override
public boolean isStreaming() {
return false;
}
}
}