Java代理转发URL流
2023-12-13 09:03:11
- 工具类 URLProxyUtil
import org.apache.http.*;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.AbortableHttpRequest;
import org.apache.http.client.utils.URIUtils;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.impl.client.SystemDefaultHttpClient;
import org.apache.http.message.BasicHttpEntityEnclosingRequest;
import org.apache.http.message.BasicHttpRequest;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.util.BitSet;
import java.util.Enumeration;
import java.util.Formatter;
/**
* 代理转发URL流
*/
public class URLProxyUtil {
private static final Logger logger = LoggerFactory.getLogger(URLProxyUtil.class);
private HttpClient proxyClient;
private String ATTR_TARGET_URI = "targetUrl";
private String ATTR_TARGET_HOST = "targetHost";
protected static final BitSet asciiQueryChars;
public URLProxyUtil() {
proxyClient = new SystemDefaultHttpClient();
}
static {
char[] c_unreserved = "_-!.~'()*".toCharArray();//plus alphanum
char[] c_punct = ",;:$&+=".toCharArray();
char[] c_reserved = "?/[]@".toCharArray();//plus punct
asciiQueryChars = new BitSet(128);
for (char c = 'a'; c <= 'z'; c++) {
asciiQueryChars.set((int) c);
}
for (char c = 'A'; c <= 'Z'; c++) {
asciiQueryChars.set((int) c);
}
for (char c = '0'; c <= '9'; c++) {
asciiQueryChars.set((int) c);
}
for (char c : c_unreserved) {
asciiQueryChars.set((int) c);
}
for (char c : c_punct) {
asciiQueryChars.set((int) c);
}
for (char c : c_reserved) {
asciiQueryChars.set((int) c);
}
asciiQueryChars.set((int) '%');//leave existing percent escapes in place
}
protected void consumeQuietly(HttpEntity entity) {
try {
EntityUtils.consume(entity);
} catch (IOException e) {//ignore
logger.error(e.getMessage(), e);
}
}
protected void copyRequestHeaders(HttpServletRequest servletRequest, HttpRequest proxyRequest) {
Enumeration enumerationOfHeaderNames = servletRequest.getHeaderNames();
while (enumerationOfHeaderNames.hasMoreElements()) {
String headerName = (String) enumerationOfHeaderNames.nextElement();
Enumeration headers = servletRequest.getHeaders(headerName);
while (headers.hasMoreElements()) {//sometimes more than one value
String headerValue = (String) headers.nextElement();
proxyRequest.addHeader(headerName, headerValue);
}
}
}
protected String rewriteUrlFromRequest(HttpServletRequest servletRequest) {
StringBuilder uri = new StringBuilder(500);
uri.append(getTargetUri(servletRequest));
// Handle the path given to the servlet
if (servletRequest.getPathInfo() != null) {//ex: /my/path.html
uri.append(encodeUriQuery(servletRequest.getPathInfo()));
}
// Handle the query string & fragment
String queryString = servletRequest.getQueryString();//ex:(following '?'): name=value&foo=bar#fragment
String fragment = null;
//split off fragment from queryString, updating queryString if found
if (queryString != null) {
int fragIdx = queryString.indexOf('#');
if (fragIdx >= 0) {
fragment = queryString.substring(fragIdx + 1);
queryString = queryString.substring(0, fragIdx);
}
}
queryString = rewriteQueryStringFromRequest(servletRequest, queryString);
if (queryString != null && queryString.length() > 0) {
uri.append('?');
uri.append(encodeUriQuery(queryString));
}
if (fragment != null) {
uri.append('#');
uri.append(encodeUriQuery(fragment));
}
return uri.toString();
}
protected String rewriteQueryStringFromRequest(HttpServletRequest servletRequest, String queryString) {
return queryString;
}
protected static CharSequence encodeUriQuery(CharSequence in) {
StringBuilder outBuf = null;
Formatter formatter = null;
try {
for (int i = 0; i < in.length(); i++) {
char c = in.charAt(i);
boolean escape = true;
if (c < 128) {
if (asciiQueryChars.get((int) c)) {
escape = false;
}
} else if (!Character.isISOControl(c) && !Character.isSpaceChar(c)) {//not-ascii
escape = false;
}
if (!escape) {
if (outBuf != null) {
outBuf.append(c);
}
} else {
//escape
if (outBuf == null) {
outBuf = new StringBuilder(in.length() + 5 * 3);
outBuf.append(in, 0, i);
formatter = new Formatter(outBuf);
}
//leading %, 0 padded, width 2, capital hex
formatter.format("%%%02X", (int) c);//TODO
}
}
} finally {
if (formatter != null) {
formatter.close();
}
}
return outBuf != null ? outBuf : in;
}
protected void copyResponseEntity(HttpResponse proxyResponse, HttpServletResponse servletResponse) throws IOException {
HttpEntity entity = proxyResponse.getEntity();
if (entity != null) {
OutputStream servletOutputStream = servletResponse.getOutputStream();
entity.writeTo(servletOutputStream);
}
}
private void setXForwardedForHeader(HttpServletRequest servletRequest,
HttpRequest proxyRequest) {
String headerName = "X-Forwarded-For";
if (true) {
String newHeader = servletRequest.getRemoteAddr();
String existingHeader = servletRequest.getHeader(headerName);
if (existingHeader != null) {
newHeader = existingHeader + ", " + newHeader;
}
proxyRequest.setHeader(headerName, newHeader);
}
}
protected void copyResponseHeaders(HttpResponse proxyResponse, HttpServletRequest servletRequest,
HttpServletResponse servletResponse) {
for (Header header : proxyResponse.getAllHeaders()) {
servletResponse.addHeader(header.getName(), header.getValue());
}
}
protected String getTargetUri(HttpServletRequest servletRequest) {
return (String) servletRequest.getAttribute(ATTR_TARGET_URI);
}
private HttpHost getTargetHost(HttpServletRequest servletRequest) {
return (HttpHost) servletRequest.getAttribute(ATTR_TARGET_HOST);
}
protected String rewriteUrlFromResponse(HttpServletRequest servletRequest, String theUrl) {
final String targetUri = getTargetUri(servletRequest);
if (theUrl.startsWith(targetUri)) {
String curUrl = servletRequest.getRequestURL().toString();//no query
String pathInfo = servletRequest.getPathInfo();
if (pathInfo != null) {
assert curUrl.endsWith(pathInfo);
curUrl = curUrl.substring(0, curUrl.length() - pathInfo.length());//take pathInfo off
}
theUrl = curUrl + theUrl.substring(targetUri.length());
}
return theUrl;
}
protected boolean doResponseRedirectOrNotModifiedLogic(
HttpServletRequest servletRequest, HttpServletResponse servletResponse,
HttpResponse proxyResponse, int statusCode)
throws ServletException, IOException {
if (statusCode >= HttpServletResponse.SC_MULTIPLE_CHOICES /* 300 */
&& statusCode < HttpServletResponse.SC_NOT_MODIFIED /* 304 */) {
Header locationHeader = proxyResponse.getLastHeader(HttpHeaders.LOCATION);
if (locationHeader == null) {
throw new ServletException("Received status code: " + statusCode
+ " but no " + HttpHeaders.LOCATION + " header was found in the response");
}
// Modify the redirect to go to this proxy servlet rather that the proxied host
String locStr = rewriteUrlFromResponse(servletRequest, locationHeader.getValue());
servletResponse.sendRedirect(locStr);
return true;
}
if (statusCode == HttpServletResponse.SC_NOT_MODIFIED) {
servletResponse.setIntHeader(HttpHeaders.CONTENT_LENGTH, 0);
servletResponse.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
return true;
}
return false;
}
public void forwardUrl(String forwardUrl, HttpServletRequest servletRequest, HttpServletResponse servletResponse) throws Exception {
String targetUri = forwardUrl;
URI targetUriObj = new URI(targetUri);
HttpHost targetHost = URIUtils.extractHost(targetUriObj);
if (servletRequest.getAttribute(ATTR_TARGET_URI) == null) {
servletRequest.setAttribute(ATTR_TARGET_URI, targetUri);
}
if (servletRequest.getAttribute(ATTR_TARGET_HOST) == null) {
servletRequest.setAttribute(ATTR_TARGET_HOST, targetHost);
}
String method = servletRequest.getMethod();
String proxyRequestUri = rewriteUrlFromRequest(servletRequest);
HttpRequest proxyRequest;
if (servletRequest.getHeader(HttpHeaders.CONTENT_LENGTH) != null ||
servletRequest.getHeader(HttpHeaders.TRANSFER_ENCODING) != null) {
HttpEntityEnclosingRequest eProxyRequest = new BasicHttpEntityEnclosingRequest(method, proxyRequestUri);
eProxyRequest.setEntity(new InputStreamEntity(servletRequest.getInputStream(), servletRequest.getContentLength()));
proxyRequest = eProxyRequest;
} else {
proxyRequest = new BasicHttpRequest(method, proxyRequestUri);
}
copyRequestHeaders(servletRequest, proxyRequest);
setXForwardedForHeader(servletRequest, proxyRequest);
HttpResponse proxyResponse = null;
try {
proxyResponse = proxyClient.execute(getTargetHost(servletRequest), proxyRequest);
int statusCode = proxyResponse.getStatusLine().getStatusCode();
copyResponseHeaders(proxyResponse, servletRequest, servletResponse);
if (doResponseRedirectOrNotModifiedLogic(servletRequest, servletResponse, proxyResponse, statusCode)) {
return;
}
servletResponse.setStatus(statusCode, proxyResponse.getStatusLine().getReasonPhrase());
copyResponseEntity(proxyResponse, servletResponse);
} catch (Exception e) {
if (proxyRequest instanceof AbortableHttpRequest) {
AbortableHttpRequest abortableHttpRequest = (AbortableHttpRequest) proxyRequest;
abortableHttpRequest.abort();
}
if (e instanceof RuntimeException) {
throw e;
}
if (e instanceof ServletException) {
throw e;
}
if (e instanceof IOException) {
throw e;
}
throw new RuntimeException(e);
} finally {
if (proxyResponse != null) {
consumeQuietly(proxyResponse.getEntity());
}
}
}
}
- 使用
URLProxyUtil proxyUtil = new URLProxyUtil();
proxyUtil.forwardUrl(url, ServletUtils.getRequest(), ServletUtils.getResponse());
文章来源:https://blog.csdn.net/qq_35957643/article/details/134858971
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!