Java代理转发URL流

  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());
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot中可以通过组合使用代理服务器和HTTP请求转发来实现代理转发。具体步骤如下: 1. 配置代理服务器 在application.properties文件中配置代理服务器的地址和端口号: ``` # 配置代理服务器地址和端口号 spring.proxies.host=proxy.example.com spring.proxies.port=8080 ``` 2. 创建RestTemplate对象 在创建RestTemplate对象时,需要设置代理服务器的地址和端口号: ```java @Configuration public class RestTemplateConfiguration { @Value("${spring.proxies.host}") private String proxyHost; @Value("${spring.proxies.port}") private int proxyPort; @Bean public RestTemplate restTemplate() { SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort)); requestFactory.setProxy(proxy); return new RestTemplate(requestFactory); } } ``` 3. 创建转发服务 创建一个转发服务,用于将HTTP请求转发到目标服务: ```java @RestController public class ForwardController { private final RestTemplate restTemplate; public ForwardController(RestTemplate restTemplate) { this.restTemplate = restTemplate; } @GetMapping("/forward") public String forward(HttpServletRequest request) { // 获取目标URL String url = request.getParameter("url"); // 发送HTTP请求获取响应 ResponseEntity<String> responseEntity = restTemplate.getForEntity(url, String.class); // 返回响应 return responseEntity.getBody(); } } ``` 4. 创建代理服务 创建一个代理服务,用于接收HTTP请求并将请求转发转发服务: ```java @RestController public class ProxyController { private final RestTemplate restTemplate; public ProxyController(RestTemplate restTemplate) { this.restTemplate = restTemplate; } @GetMapping("/proxy") public String proxy(HttpServletRequest request) { // 获取转发URL String url = request.getParameter("url"); // 构造转发URL String forwardUrl = "http://localhost:8080/forward?url=" + url; // 发送HTTP请求获取响应 ResponseEntity<String> responseEntity = restTemplate.getForEntity(forwardUrl, String.class); // 返回响应 return responseEntity.getBody(); } } ``` 5. 配置路由规则 在application.properties文件中配置路由规则: ``` # 配置路由规则 spring.cloud.gateway.routes[0].id=proxy spring.cloud.gateway.routes[0].uri=http://localhost:8081 spring.cloud.gateway.routes[0].predicates[0]=Path=/proxy/** ``` 6. 启动服务 启动代理服务和转发服务,访问代理服务的URL即可实现代理转发。 以上就是使用Spring Boot实现代理转发的步骤。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值