springboot反向代理Controller实现

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.net.ssl.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.cert.X509Certificate;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;

@Controller
public class ProxyController {

    //TARGET_URL为需要代理的目标接口地址
    private static final String TARGET_URL = "http://localhost:8080";

    private static final Set<String> HOP_BY_HOP;

    static {
        disableCertificateValidation();

        Set<String> skipHeaders = new HashSet<>();
        skipHeaders.add("connection");
        skipHeaders.add("keep-alive");
        skipHeaders.add("proxy-authenticate");
        skipHeaders.add("proxy-authorization");
        skipHeaders.add("te");
        skipHeaders.add("trailers");
        skipHeaders.add("transfer-encoding");
        skipHeaders.add("upgrade");
        skipHeaders.add("host");
        HOP_BY_HOP = Collections.unmodifiableSet(skipHeaders);
    }

    private static void disableCertificateValidation() {
        try {
            TrustManager[] trustAllCerts = new TrustManager[]{
                    new X509TrustManager() {
                        public X509Certificate[] getAcceptedIssuers() {
                            return null;
                        }
                        public void checkClientTrusted(X509Certificate[] certs, String authType) {}
                        public void checkServerTrusted(X509Certificate[] certs, String authType) {}
                    }
            };
            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null, trustAllCerts, new java.security.SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

            HostnameVerifier allHostsValid = (hostname, session) -> true;
            HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @RequestMapping(value = "/proxyApi/**")
    public void proxy(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String base = TARGET_URL.trim();
        if (base.endsWith("/")) {
            base = base.substring(0, base.length() - 1);
        }

        String uri = request.getRequestURI();
        String ctx = request.getContextPath();
        String path = uri.startsWith(ctx) ? uri.substring(ctx.length()) : uri;
        StringBuilder targetUrl = new StringBuilder(base).append(path);

        String query = request.getQueryString();
        if (query != null) {
            targetUrl.append("?").append(query);
        }

        URL url = new URL(targetUrl.toString());
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();

        try {
            String method = request.getMethod();
            conn.setRequestMethod(method);
            conn.setDoInput(true);

            boolean hasBody = "POST".equals(method) || "PUT".equals(method) || "PATCH".equals(method);
            conn.setDoOutput(hasBody);

            Enumeration<String> headerNames = request.getHeaderNames();
            while (headerNames.hasMoreElements()) {
                String name = headerNames.nextElement();
                String lower = name.toLowerCase();

                if (HOP_BY_HOP.contains(lower)) {
                    continue;
                }
                if (hasBody && ("content-length".equals(lower) || "transfer-encoding".equals(lower))) {
                    continue;
                }

                Enumeration<String> values = request.getHeaders(name);
                while (values.hasMoreElements()) {
                    conn.addRequestProperty(name, values.nextElement());
                }
            }

            if (hasBody) {
                try (InputStream in = request.getInputStream();
                     OutputStream out = conn.getOutputStream()) {
                    byte[] buffer = new byte[8192];
                    int len;
                    while ((len = in.read(buffer)) != -1) {
                        out.write(buffer, 0, len);
                    }
                }
            }

            int status = conn.getResponseCode();
            response.setStatus(status);

            for (String key : conn.getHeaderFields().keySet()) {
                if (key == null || HOP_BY_HOP.contains(key.toLowerCase())) {
                    continue;
                }
                response.setHeader(key, conn.getHeaderField(key));
            }

            try (InputStream in = conn.getInputStream();
                 OutputStream out = response.getOutputStream()) {
                byte[] buffer = new byte[8192];
                int len;
                while ((len = in.read(buffer)) != -1) {
                    out.write(buffer, 0, len);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            conn.disconnect();
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值