Zuul proxy - how to forward requests to services depending on request path(ZUUL代理-如何根据请求路径将请求转发到服务)
问题描述
问题
如何在Spring Cloud应用中转发请求?我需要根据URI的部分将请求转发到其他服务。
例如
HTTP GET http://user-application/api/users,返回用户JSON。HTTP GET http://user-application/api/proxy/jobs-application/api/jobs,返回作业JSON,但此请求应转发到另一个应用程序:HTTP GET http://jobs-application/api/jobs。- 不仅是
GET,还可以使用任何HTTP方法。 
- 不仅是
 
上下文
我有一个SpringBoot应用程序用户应用程序,它具有返回数据的REST终结点。
例如GET http://user-application/api/users将以JSON格式返回用户。
用户应用程序也有一个应将请求转发到其他应用程序的HTTP终结点--我们将其中一个应用程序称为作业应用程序
。 作为示例,该端点是,GET http://user-application/api/proxy/jobs-application/api/jobs
请注意,初始请求发送到用户应用程序,然后转发到作业应用程序。
接近
我提出了一些我思考的方法。也许你以前做过类似的事情,所以你可以分享你这样做的经验。或者甚至改进我的方法之一。
代理控制器方法
我将在用户应用程序中使用映射/proxy
ProxyController
@Controller
@RequestMaping("/proxy/**")
ProxyController
public void proxy(final HttpServletRequest request, HttpResponse response) {
    final String requestUri = request.getRequestUri();
    if (!requestUri.startsWith("/api/proxy/")) {
        return null; // Do not proxy
    }
    final int proxyIndex = "/api/proxy/".lenght(); // Can be made a constant
    final String proxiedUrl = requestUri.subString(proxyIndex, requestUri.lenght());
    final Optional<String> payload = retrievePayload(request);
    final Headers headers = retrieveHeaders(request);
    final HttpRequest proxyRequest = buildProxyRequest(request, headers);
    payload.ifPresent(proxyRequest::setPayload);
    final HttpResponse proxyResponse = httpClient.execute(proxyRequest)
    pdateResponse(response, proxyResponse);
}
这种方法的问题是,我必须编写大量代码来构建代理请求,以检查它是否有有效负载,如果有,将其复制到代理请求中,然后将标头、Cookie等复制到代理请求中,将HTTP谓词复制到代理请求中。然后,当我收到代理响应时,我必须将其详细信息填充到响应中。
Zuul方法
我受到ZuulFilters的启发:
- https://www.baeldung.com/spring-rest-with-zuul-proxy
 - https://stackoverflow.com/a/47856576/4587961
 
@Component
public class ProxyFilter extends ZuulFilter {
    private static final String PROXY_PART = "/api/proxy";
    private static final int PART_LENGTH = PROXY_PART.length();
    @Autowired
    public ProxyFilter() {
    }
    @Override
    public boolean shouldFilter() {
        final RequestContext context = RequestContext.getCurrentContext();
        final String requestURI = retrieveRequestUri(context);
        return requestURI.startsWith(PROXY_PART);
    }
    @Override
    public Object run() {
        final RequestContext context = RequestContext.getCurrentContext();
        final String requestURI = retrieveRequestUri(context);
        final String forwardUri = requestURI.substring(PART_LENGTH);
        context.setRouteHost(buildUrl(forwardUri));
        return null;
    }
    @Override
    public String filterType() {
        return "proxy";
    }
    @Override
    public int filterOrder() {
        return 0;
    }
    private String retrieveRequestUri(final RequestContext context) {
        final HttpServletRequest request = context.getRequest();
        return request.getRequestURI();
    }
    private URL buildUrl(final String uri) {
        try {
            return new URL(uri);
        } catch (MalformedURLException e) {
            throw new RuntimeException(String.format("Failed to forward request uri %s}.", uri), e);
        }
    }
}
这段代码使我可以更轻松地转发请求。然而,我们也在Spring Cloud Zuul中使用了客户端负载均衡器Ribbon和断路器hystrix。如何启用这些功能?是否将在context.setRouteHost(forwardUrl);中启用它们
推荐答案
我想添加另一种方法,或许它也可以工作。
用于配置Zuul代理方法的静态应用程序.yml文件
此方法不需要动态ZUUL筛选器。
Application.yml
zuul:
  routes:
    user-application:
      path: /api/users/**
      serviceId: user-service
      stripPrefix: false
      sensitiveHeaders:
    #  I have to define all other services similarly.
    jobs-application:
      path: /api/proxy/jobs/**
      serviceId: jobs-application
      stripPrefix: true
      sensitiveHeaders:
仅当我在部署用户应用程序之前知道我的客户端需要调用的所有服务时,它才会起作用。如果动态添加新的应用程序,该怎么办?然后我必须更新配置。
这篇关于ZUUL代理-如何根据请求路径将请求转发到服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:ZUUL代理-如何根据请求路径将请求转发到服务
				
        
 
            
        基础教程推荐
- Java 实例变量在两个语句中声明和初始化 2022-01-01
 - 不推荐使用 Api 注释的描述 2022-01-01
 - 在 Java 中创建日期的正确方法是什么? 2022-01-01
 - 如何在 Spring @Value 注解中正确指定默认值? 2022-01-01
 - 多个组件的复杂布局 2022-01-01
 - Java Swing计时器未清除 2022-01-01
 - 从 python 访问 JVM 2022-01-01
 - 大摇大摆的枚举 2022-01-01
 - 验证是否调用了所有 getter 方法 2022-01-01
 - 如何在 JFrame 中覆盖 windowsClosing 事件 2022-01-01
 
    	
    	
    	
    	
    	
    	
    	
    	
						
						
						
						
						
				
				
				
				