package com.jx.zuul.server.filter;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.Header;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.commons.httpclient.ApacheHttpClientConnectionManagerFactory;
import org.springframework.cloud.commons.httpclient.ApacheHttpClientFactory;
import org.springframework.cloud.netflix.zuul.filters.ProxyRequestHelper;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties;
import org.springframework.cloud.netflix.zuul.filters.route.SimpleHostRoutingFilter;
import org.springframework.cloud.netflix.zuul.util.ZuulRuntimeException;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.util.UriUtils;
import org.springframework.web.util.WebUtils;
import com.netflix.zuul.context.RequestContext;
@Component
public class RewriteSimpleHostRoutingFilter extends SimpleHostRoutingFilter {
private static final Log log = LogFactory.getLog(RewriteSimpleHostRoutingFilter.class);
@Autowired
private ProxyRequestHelper helper;
private CloseableHttpClient httpClient=null;
public CloseableHttpClient instanceCloseableHttpClient() {
if(null == httpClient) {
CloseableHttpClient client = HttpClientBuilder.create().build();
httpClient=client;
}
return httpClient;
}
public RewriteSimpleHostRoutingFilter(ProxyRequestHelper helper, ZuulProperties properties,
ApacheHttpClientConnectionManagerFactory connectionManagerFactory,
ApacheHttpClientFactory httpClientFactory) {
super(helper, properties, connectionManagerFactory, httpClientFactory);
}
@Override
public Object run() {
RequestContext context = RequestContext.getCurrentContext();
HttpServletRequest request = context.getRequest();
MultiValueMap<String, String> headers = this.helper
.buildZuulRequestHeaders(request);
MultiValueMap<String, String> params = this.helper
.buildZuulRequestQueryParams(request);
String verb = getVerb(request);
InputStream requestEntity = getRequestBody(request);
if (getContentLength(request) < 0) {
context.setChunkedRequestBody();
}
String uri = this.helper.buildZuulRequestURI(request);
this.helper.addIgnoredHeaders();
try {
CloseableHttpResponse response = forward(instanceCloseableHttpClient(), verb, uri, request,
headers, params, requestEntity);
setResponse(response);
}
catch (Exception ex) {
throw new ZuulRuntimeException(handleException(ex));
}
return null;
}
private String getVerb(HttpServletRequest request) {
String sMethod = request.getMethod();
return sMethod.toUpperCase();
}
private void setResponse(HttpResponse response) throws IOException {
RequestContext.getCurrentContext().set("zuulResponse", response);
this.helper.setResponse(response.getStatusLine().getStatusCode(),
response.getEntity() == null ? null : response.getEntity().getContent(),
revertHeaders(response.getAllHeaders()));
}
private MultiValueMap<String, String> revertHeaders(Header[] headers) {
MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
for (Header header : headers) {
String name = header.getName();
if (!map.containsKey(name)) {
map.put(name, new ArrayList<String>());
}
map.get(name).add(header.getValue());
}
return map;
}
private CloseableHttpResponse forward(CloseableHttpClient httpclient, String verb,
String uri, HttpServletRequest request, MultiValueMap<String, String> headers,
MultiValueMap<String, String> params, InputStream requestEntity)
throws Exception {
System.out.println("覆盖SimpleHostRoutingFilter");
Map<String, Object> info = this.helper.debug(verb, uri, headers, params,
requestEntity);
URL host = RequestContext.getCurrentContext().getRouteHost();
HttpHost httpHost = getHttpHost(host);
long contentLength = getContentLength(request);
ContentType contentType = null;
if (request.getContentType() != null) {
contentType = ContentType.parse(request.getContentType());
}
InputStreamEntity entity = new InputStreamEntity(requestEntity, contentLength,
contentType);
uri = UriUtils.decode(uri, characterEncoding(request));
HttpRequest httpRequest = buildHttpRequest(verb, uri, entity, headers, params,
request);
try {
log.debug(httpHost.getHostName() + " " + httpHost.getPort() + " "
+ httpHost.getSchemeName());
CloseableHttpResponse zuulResponse = forwardRequest(httpclient, httpHost,
httpRequest);
this.helper.appendDebug(info, zuulResponse.getStatusLine().getStatusCode(),
revertHeaders(zuulResponse.getAllHeaders()));
return zuulResponse;
}
finally {
}
}
private CloseableHttpResponse forwardRequest(CloseableHttpClient httpclient,
HttpHost httpHost, HttpRequest httpRequest) throws IOException {
return httpclient.execute(httpHost, httpRequest);
}
private String characterEncoding(HttpServletRequest request) {
return request.getCharacterEncoding() != null ? request.getCharacterEncoding()
: WebUtils.DEFAULT_CHARACTER_ENCODING;
}
private HttpHost getHttpHost(URL host) {
HttpHost httpHost = new HttpHost(host.getHost(), host.getPort(),
host.getProtocol());
return httpHost;
}
}