<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
</parent>
<groupId>com.yxs.proxy</groupId>
<artifactId>proxy-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<spring-boot.version>2.2.2.RELEASE</spring-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<fork>true</fork>
<addResources>true</addResources>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
package com.yxs.proxy.controller;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.util.StreamUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.net.ssl.SSLContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
@Slf4j
@RestController
@RequestMapping("/proxy")
public class ProxyHttpReqController {
@Value("${forwardTargetAddress}")
private String forwardTargetAddress;
@Value("${reverseTargetAddress}")
private String reverseTargetAddress;
@RequestMapping("/forward/**")
public void forward(HttpServletRequest request, HttpServletResponse response) throws URISyntaxException, IOException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
URI uri = new URI(request.getRequestURI());
String path = uri.getPath();
String target = (StringUtils.isEmpty(request.getHeader("forwardTargetAddress")) ? forwardTargetAddress : request.getHeader("forwardTargetAddress"))
+ path.replace("/proxy/forward", "");
router(request, response, target);
}
@RequestMapping("/reverse/**")
public void reverse(HttpServletRequest request, HttpServletResponse response) throws URISyntaxException, IOException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
URI uri = new URI(request.getRequestURI());
String path = uri.getPath();
String target = reverseTargetAddress + path.replace("/proxy/reverse", "");
router(request, response, target);
}
private static void router(HttpServletRequest request, HttpServletResponse response, String target) throws URISyntaxException, IOException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
String query = request.getQueryString();
if (query != null && !query.isEmpty() && !"null".equals(query)) {
target = target + "?" + query;
}
URI newUri = new URI(target);
String methodName = request.getMethod();
HttpMethod httpMethod = HttpMethod.resolve(methodName);
if (httpMethod == null) {
return;
}
SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, (chain, authType) -> true).build();
NoopHostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, hostnameVerifier);
CloseableHttpClient httpClient = HttpClients.custom()
.setSSLSocketFactory(sslsf)
.build();
ClientHttpRequest delegate = new HttpComponentsClientHttpRequestFactory(httpClient).createRequest(newUri, httpMethod);
Enumeration<String> headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
Enumeration<String> v = request.getHeaders(headerName);
List<String> arr = new ArrayList<>();
while (v.hasMoreElements()) {
arr.add(v.nextElement());
}
delegate.getHeaders().addAll(headerName, arr);
}
StreamUtils.copy(request.getInputStream(), delegate.getBody());
try (ClientHttpResponse clientHttpResponse = delegate.execute()) {
response.setStatus(clientHttpResponse.getStatusCode().value());
clientHttpResponse.getHeaders().forEach((key, value) -> value.forEach(it -> {
response.setHeader(key, it);
}));
StreamUtils.copy(clientHttpResponse.getBody(), response.getOutputStream());
}
}
}