通过springboot转发请求

问题描述 投票:0回答:1

由于Safari浏览器严格的cookie政策,我无法在exalple1.com域页面上调用exalple2.com接口。现在我想通过转发后端来解决这个问题,即页面上的所有请求都发送到exalple1.com。如果页面要调用的接口是exalple2.com/user/mine,则页面可以是exalple1.com/exalple2-api/user/mine,后端转发到exalple2.com/user/mine,并返回return从 exalple2.com/user/mine 获取到前端的值。请求http://example1.com/example2-api/user/mine时页面携带的所有参数都需要原样传输到http://example2.com/user/mine,例如body 或 url 或请求标头中的参数。您有什么想法通过拦截器来实现这个功能吗?非常感谢您的帮助!

我尝试使用请求接收到的信息重新生成HTTP请求并使用RestTemplate发送它,但响应是乱码。

import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class ForwardInterceptor implements HandlerInterceptor {
    private RestTemplate restTemplate;

    public ForwardInterceptor(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 获取原始请求的URL、请求方法、请求体和请求头
        String originalUrl = request.getRequestURI();
        String originalMethod = request.getMethod();
        String originalBody = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
        HttpHeaders originalHeaders = new HttpHeaders();
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            String headerValue = request.getHeader(headerName);
            originalHeaders.add(headerName, headerValue);
        }

        // 构建转发请求的URL
        String forwardUrl = "http://example2.com" + originalUrl;

        // 创建转发请求
        RequestEntity<String> requestEntity = new RequestEntity<>(originalBody, originalHeaders, HttpMethod.valueOf(originalMethod), URI.create(forwardUrl));

        // 发送转发请求
        ResponseEntity<String> responseEntity = restTemplate.exchange(requestEntity, String.class);

        // 将转发请求的响应设置到原始响应中
        response.setStatus(responseEntity.getStatusCodeValue());
        response.setContentType(responseEntity.getHeaders().getContentType().toString());
        response.getWriter().write(responseEntity.getBody());

        return false; // 停止后续处理
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 在请求处理完成后的操作
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 在请求完成后的操作
    }
}

java spring spring-boot spring-mvc
1个回答
0
投票

因为客户端发送请求时,带上了Accept-Encoding,告诉服务器可以用GZIP压缩返回,但是RestTemplate默认不支持GZIP,所以当返回数据转换成字符串时,甚至字母和数字。

解决方案:

  1. 手动去掉Accept-Entiding,直接去掉代码中的请求头

    originalHeaders.remove(HttpHeaders.ACCEPT_ENCODING);

  2. 配置RestTemplate,支持GZIP

  • this.restTemplate = new RestTemplate(new HttpComponentsClientHttpRequestFactory(HttpClientBuilder.create().build()));

  • 添加httpclient依赖

    org.apache.httpcomponents http客户端
© www.soinside.com 2019 - 2024. All rights reserved.