Java代理转发URL流

2023-12-13 09:03:11
  1. 工具类 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());
	            }
	        }

	    }
}

  1. 使用
URLProxyUtil proxyUtil = new URLProxyUtil();
proxyUtil.forwardUrl(url, ServletUtils.getRequest(), ServletUtils.getResponse());

文章来源:https://blog.csdn.net/qq_35957643/article/details/134858971
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。