package com.terra.system.helper;
|
|
import org.apache.http.*;
|
import org.apache.http.client.config.CookieSpecs;
|
import org.apache.http.client.config.RequestConfig;
|
import org.apache.http.client.utils.URIUtils;
|
import org.apache.http.entity.InputStreamEntity;
|
import org.apache.http.impl.client.CloseableHttpClient;
|
import org.apache.http.impl.client.HttpClients;
|
import org.apache.http.message.BasicHeader;
|
import org.apache.http.message.BasicHttpEntityEnclosingRequest;
|
import org.apache.http.message.BasicHttpRequest;
|
import org.apache.http.message.HeaderGroup;
|
import org.apache.http.util.EntityUtils;
|
|
import javax.servlet.ServletException;
|
import javax.servlet.http.Cookie;
|
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletResponse;
|
import java.io.IOException;
|
import java.io.OutputStream;
|
import java.net.HttpCookie;
|
import java.net.URI;
|
import java.net.URISyntaxException;
|
import java.util.Enumeration;
|
|
/**
|
* Http帮助类
|
* @author WWW
|
*/
|
public class HttpHelper {
|
private final static String HTTP_SLASH2 = "://";
|
|
private final static String HTTP_SLASH = "/";
|
|
private final static Integer THREE = 3;
|
|
protected static final HeaderGroup HOP_HEADERS;
|
|
static {
|
HOP_HEADERS = new HeaderGroup();
|
|
String[] headers = new String[]{
|
"Connection", "Keep-Alive", "Proxy-Authenticate", "Proxy-Authorization",
|
"TE", "Trailers", "Transfer-Encoding", "Upgrade",
|
//"X-RateLimit-Burst-Capacity", "X-RateLimit-Remaining", "X-RateLimit-Replenish-Rate",
|
"Access-Control-Allow-Origin", "Access-Control-Allow-Credentials", "Access-Control-Allow-Headers"};
|
|
for (String header : headers) {
|
HOP_HEADERS.addHeader(new BasicHeader(header, null));
|
}
|
}
|
|
public void service(HttpServletRequest request, HttpServletResponse response, String url, String cookie) throws ServletException, IOException {
|
HttpRequest proxyRequest;
|
if (request.getHeader(HttpHeaders.CONTENT_LENGTH) != null || request.getHeader(HttpHeaders.TRANSFER_ENCODING) != null) {
|
proxyRequest = newProxyRequestWithEntity(request, url);
|
} else {
|
proxyRequest = new BasicHttpRequest(request.getMethod(), url);
|
}
|
|
HttpHost host = this.getTargetHost(url);
|
// copyRequestHeaders(request, proxyRequest, host);
|
//setXrForwardedForHeader(request, proxyRequest);
|
|
if (!StringHelper.isEmpty(cookie)) {
|
proxyRequest.addHeader("Cookie", cookie + "; ");
|
}
|
|
CloseableHttpClient client = null;
|
HttpResponse proxyResponse = null;
|
|
try {
|
client = this.createHttpClient();
|
proxyResponse = client.execute(host, proxyRequest);
|
|
int statusCode = proxyResponse.getStatusLine().getStatusCode();
|
// response.setStatus(statusCode, proxyResponse.getStatusLine().getReasonPhrase())
|
response.setStatus(statusCode);
|
|
copyResponseHeaders(proxyResponse, request, response, url);
|
|
if (statusCode == HttpServletResponse.SC_NOT_MODIFIED) {
|
response.setIntHeader(HttpHeaders.CONTENT_LENGTH, 0);
|
} else {
|
copyResponseEntity(proxyResponse, response);
|
}
|
} catch (Exception ex) {
|
throw new ServletException(ex.getMessage());
|
} finally {
|
if (proxyResponse != null) {
|
EntityUtils.consumeQuietly(proxyResponse.getEntity());
|
}
|
if (client != null) {
|
client.close();
|
}
|
}
|
}
|
|
protected HttpRequest newProxyRequestWithEntity(HttpServletRequest request, String url) throws IOException {
|
String method = request.getMethod();
|
HttpEntityEnclosingRequest proxyRequest = new BasicHttpEntityEnclosingRequest(method, url);
|
proxyRequest.setEntity(new InputStreamEntity(request.getInputStream(), getContentLength(request)));
|
//String str = EntityUtils.toString(proxyRequest.getEntity(), "UTF-8")
|
|
return proxyRequest;
|
}
|
|
private long getContentLength(HttpServletRequest request) {
|
String contentLengthHeader = request.getHeader("Content-Length");
|
if (contentLengthHeader != null) {
|
return Long.parseLong(contentLengthHeader);
|
}
|
|
return -1L;
|
}
|
|
protected void copyRequestHeaders(HttpServletRequest request, HttpRequest proxyRequest, HttpHost host) {
|
@SuppressWarnings("unchecked")
|
Enumeration<String> enumerationOfHeaderNames = request.getHeaderNames();
|
|
while (enumerationOfHeaderNames.hasMoreElements()) {
|
String headerName = enumerationOfHeaderNames.nextElement();
|
copyRequestHeader(request, proxyRequest, host, headerName);
|
}
|
}
|
|
protected void copyRequestHeader(HttpServletRequest request, HttpRequest proxyRequest, HttpHost host, String headerName) {
|
if (headerName.equalsIgnoreCase(HttpHeaders.CONTENT_LENGTH) || HOP_HEADERS.containsHeader(headerName)) {
|
return;
|
}
|
|
@SuppressWarnings("unchecked")
|
Enumeration<String> headers = request.getHeaders(headerName);
|
while (headers.hasMoreElements()) {
|
String headerValue = headers.nextElement();
|
if (headerName.equalsIgnoreCase(HttpHeaders.HOST)) {
|
headerValue = host.getHostName();
|
if (host.getPort() != -1) {
|
headerValue += ":" + host.getPort();
|
}
|
} else if (headerName.equalsIgnoreCase(org.apache.http.cookie.SM.COOKIE)) {
|
headerValue = getRealCookie(headerValue);
|
}
|
|
proxyRequest.addHeader(headerName, headerValue);
|
}
|
}
|
|
protected HttpHost getTargetHost(String url) throws ServletException {
|
try {
|
URI uri = new URI(url);
|
|
return URIUtils.extractHost(uri);
|
} catch (URISyntaxException ex) {
|
throw new ServletException(ex.getMessage());
|
}
|
}
|
|
protected String getRealCookie(String cookieValue) {
|
StringBuilder escapedCookie = new StringBuilder();
|
|
String[] cookies = cookieValue.split("[;,]");
|
for (String cookie : cookies) {
|
String[] cookieSplit = cookie.split("=");
|
if (cookieSplit.length == 2) {
|
String cookieName = cookieSplit[0].trim();
|
if (cookieName.startsWith(cookieName)) {
|
cookieName = cookieName.substring(cookieName.length());
|
if (escapedCookie.length() > 0) {
|
escapedCookie.append("; ");
|
}
|
escapedCookie.append(cookieName).append("=").append(cookieSplit[1].trim());
|
}
|
}
|
}
|
|
return escapedCookie.toString();
|
}
|
|
private void setXrForwardedForHeader(HttpServletRequest request, HttpRequest proxyRequest) {
|
String forHeaderName = "X-Forwarded-For";
|
String forHeader = request.getRemoteAddr();
|
String existingForHeader = request.getHeader(forHeaderName);
|
if (existingForHeader != null) {
|
forHeader = existingForHeader + ", " + forHeader;
|
}
|
proxyRequest.setHeader(forHeaderName, forHeader);
|
|
String protoHeaderName = "X-Forwarded-Proto";
|
String protoHeader = request.getScheme();
|
proxyRequest.setHeader(protoHeaderName, protoHeader);
|
}
|
|
protected CloseableHttpClient createHttpClient() {
|
RequestConfig requestConfig = RequestConfig.custom()
|
.setRedirectsEnabled(false)
|
.setCookieSpec(CookieSpecs.IGNORE_COOKIES)
|
.setConnectTimeout(-1)
|
.setSocketTimeout(-1)
|
.build();
|
|
// return HttpClientBuilder.create().setDefaultRequestConfig(requestConfig).build()
|
return HttpClients.custom()
|
.setDefaultRequestConfig(requestConfig)
|
.build();
|
}
|
|
protected void copyResponseHeaders(HttpResponse proxyResponse, HttpServletRequest request, HttpServletResponse response, String url) {
|
for (Header header : proxyResponse.getAllHeaders()) {
|
copyResponseHeader(request, response, header, url);
|
}
|
}
|
|
protected void copyResponseHeader(HttpServletRequest request, HttpServletResponse response, Header header, String url) {
|
String headerName = header.getName();
|
if (HOP_HEADERS.containsHeader(headerName)) {
|
return;
|
}
|
|
String headerValue = header.getValue();
|
if (headerName.equalsIgnoreCase(org.apache.http.cookie.SM.SET_COOKIE) || headerName.equalsIgnoreCase(org.apache.http.cookie.SM.SET_COOKIE2)) {
|
copyProxyCookie(request, response, headerValue);
|
} else if (headerName.equalsIgnoreCase(HttpHeaders.LOCATION)) {
|
response.addHeader(headerName, rewriteUrlFromResponse(request, url, headerValue));
|
} else {
|
response.addHeader(headerName, headerValue);
|
}
|
}
|
|
protected void copyProxyCookie(HttpServletRequest request, HttpServletResponse response, String headerValue) {
|
String path = request.getContextPath() + request.getServletPath();
|
if (path.isEmpty()) {
|
path = "/";
|
}
|
|
for (HttpCookie cookie : HttpCookie.parse(headerValue)) {
|
Cookie servletCookie = new Cookie(cookie.getName(), cookie.getValue());
|
servletCookie.setComment(cookie.getComment());
|
servletCookie.setMaxAge((int) cookie.getMaxAge());
|
servletCookie.setPath(path);
|
|
servletCookie.setSecure(cookie.getSecure());
|
servletCookie.setVersion(cookie.getVersion());
|
response.addCookie(servletCookie);
|
}
|
}
|
|
protected String rewriteUrlFromResponse(HttpServletRequest request, String targetUri, String theUrl) {
|
if (theUrl.startsWith(targetUri)) {
|
StringBuffer curUrl = request.getRequestURL();
|
|
int pos;
|
if ((pos = curUrl.indexOf(HTTP_SLASH2)) >= 0) {
|
if ((pos = curUrl.indexOf(HTTP_SLASH, pos + THREE)) >= 0) {
|
curUrl.setLength(pos);
|
}
|
}
|
|
curUrl.append(request.getContextPath());
|
curUrl.append(request.getServletPath());
|
curUrl.append(theUrl, targetUri.length(), theUrl.length());
|
|
return curUrl.toString();
|
}
|
|
return theUrl;
|
}
|
|
protected void copyResponseEntity(HttpResponse proxyResponse, HttpServletResponse response) throws IOException {
|
HttpEntity entity = proxyResponse.getEntity();
|
if (entity != null) {
|
//String str = EntityUtils.toString(entity, "UTF-8")
|
OutputStream servletOutputStream = response.getOutputStream();
|
entity.writeTo(servletOutputStream);
|
}
|
}
|
}
|