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

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

作者: 小方块886 | 来源:发表于2022-09-18 16:53 被阅读0次
    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<String, MultipartFile> map = mulReq.getFileMap();
                List<MultipartFile> valueList = new ArrayList<MultipartFile>(map.values());
                MultiValueMap<String, Object> 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<MultiValueMap<String, Object>> files = new HttpEntity<MultiValueMap<String, Object>>(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<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());
                // 执行远程调用
                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将外网请求转发到内网服务器中并直接返回数据

          本文链接:https://www.haomeiwen.com/subject/vkmportx.html