如何在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端点,该端点应将请求转发给其他应用程序-我们将其中一个称为 Jobs应用程序。
例如,此端点为HTTP {ANY_METHOD} /api/proxy/{dynamic-service}/{dynamic-path}
,
GET http://user-application/api/proxy/jobs-application/api/jobs
请注意,初始请求来自用户应用程序,然后转发至工作应用程序。
我提出了一些我所考虑的方法。也许您过去曾经做过类似的事情,所以您可以分享自己的经验。甚至改进我的一种方法。
我会在用户应用中使用映射ProxyController
/proxy
@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动词复制到代理请求中。然后,当我收到代理响应时,必须将其详细信息填充到响应中。
我的灵感来自ZuulFilters:
@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中的客户端负载平衡器功能区和断路器Hystrix。如何启用这些功能?是否可以在context.setRouteHost(forwardUrl);
答案 0 :(得分:0)
我想添加另一种方法,也许它也可以工作。
这种方法不需要动态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:
仅当我知道我的客户需要在部署用户应用程序之前调用的所有服务时,此功能才有效。如果动态添加新应用程序怎么办?然后,我将不得不更新配置。