springboot将外网请求转发到内网服务器中并直接返回数据

import org.apache.commons.io.FileUtils;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StreamUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;

@RestController
public class ProxyController{

    // 内网服务器地址+端口
    private String targetAddr = "http://10.0.0.100:9000";

    /**
     * 代理所有请求
     *
     * @param request
     * @param response
     * @throws Exception
     */
    @RequestMapping(value = "/proxy/**")
    public void proxy(HttpServletRequest request, HttpServletResponse response) throws IOException, URISyntaxException {
        // String url = URLDecoder.decode(request.getRequestURL().toString(), "UTF-8");
        URI uri = new URI(request.getRequestURI());
        String path = uri.getPath();
        String query = request.getQueryString();
        String target = targetAddr + path.replace("/proxy", "");
        if (query != null && !query.equals("") && !query.equals("null")) {
            target = target + "?" + query;
        }
        URI newUri = new URI(target);
        // 执行代理查询
        String methodName = request.getMethod();

        HttpMethod httpMethod = HttpMethod.resolve(methodName);
        if (httpMethod == null) {
            return;
        }
        InputStream stream = null;
        String contentType = request.getContentType();

        // 兼容文件上传的请求
        if (contentType != null && contentType.startsWith("multipart/form-data")){
            MultipartHttpServletRequest mulReq = (MultipartHttpServletRequest) request;
            Map map = mulReq.getFileMap();
            List valueList = new ArrayList(map.values());
            MultiValueMap params = new LinkedMultiValueMap();
            for (MultipartFile file : valueList) {
                File newFile = File.createTempFile("temp",file.getOriginalFilename());
                FileUtils.copyInputStreamToFile(file.getInputStream(), newFile);
                FileSystemResource resource = new FileSystemResource(newFile);
                params.add(file.getName(), resource);

            }
            RestTemplate restTemplate = new RestTemplate();

            // 设置请求头
            HttpHeaders headers = new HttpHeaders();
            while (headerNames.hasMoreElements()) {
                String headerName = headerNames.nextElement();
                System.out.println(headerName + ":" + request.getHeader(headerName));
                headers.set(headerName,request.getHeader(headerName));
            }

            // 手动设置请求头的token信息
            headers.set("Authorization",request.getHeader("Authorization"));

            // 用HttpEntity封装整个请求报文
            HttpEntity> files = new HttpEntity>(params,headers);

            String res = restTemplate.postForEntity(target, files, String.class).getBody();
            InputStream is =new ByteArrayInputStream(res.getBytes("UTF-8"));
            stream = is;
        // 其他请求例如get post put delete都可使用
        }else {
            ClientHttpRequest delegate = new SimpleClientHttpRequestFactory().createRequest(newUri, httpMethod);
            Enumeration headerNames = request.getHeaderNames();
            // 设置请求头
            while (headerNames.hasMoreElements()) {
                String headerName = headerNames.nextElement();
                Enumeration v = request.getHeaders(headerName);
                List arr = new ArrayList<>();
                while (v.hasMoreElements()) {
                    arr.add(v.nextElement());
                }
                delegate.getHeaders().addAll(headerName, arr);
            }
            StreamUtils.copy(request.getInputStream(), delegate.getBody());
            // 执行远程调用
            ClientHttpResponse clientHttpResponse = delegate.execute();
            response.setStatus(clientHttpResponse.getStatusCode().value());

            // 设置响应头
            clientHttpResponse.getHeaders().forEach((key, value) -> value.forEach(it -> {
                response.setHeader(key, it);
            }));
            stream = clientHttpResponse.getBody();
        }

        // 将获取到的输入流再次输出到页面输出流中
        StreamUtils.copy(stream, response.getOutputStream());
    }
}

你可能感兴趣的:(springboot将外网请求转发到内网服务器中并直接返回数据)