Spring 集成:保留 http 错误代码和正文作为响应
Spring integration: preserve http error code and body in response
我有一个入站 http 网关,其传入消息被传递到出站 http 网关(使用集成 java dsl)。
当出站网关响应的 http 状态为 200 时,出站响应会按预期返回到入站网关的调用方。
但是,当出站网关响应特定的客户端错误(例如 423 锁定或 403 禁止)时,入站网关的调用方会收到 500 和包含字符串异常的正文消息。
我了解这是因为 SI 将出站 http 错误作为异常处理。但在我的例子中,我需要通过错误状态 和 将出站响应附带的响应主体返回给入站网关的调用者,以获取特定的错误代码。我该怎么做?
我们将这种情况称为 HTTP 代理,并且有一些关于此事的测试用例:https://github.com/spring-projects/spring-integration/blob/master/spring-integration-http/src/test/java/org/springframework/integration/http/dsl/HttpDslTests.java
我刚刚做了一些调查,这是你需要的:
IntegrationFlows
.from(Http.inboundGateway("/service")
.requestMapping(r -> r.params("name"))
.errorChannel("httpProxyErrorFlow.input"))
...
@Bean
public IntegrationFlow httpProxyErrorFlow() {
return f -> f
.transform(Throwable::getCause)
.<HttpClientErrorException>handle((p, h) ->
MessageBuilder.withPayload(p.getResponseBodyAsString())
.setHeader(HttpHeaders.STATUS_CODE, p.getStatusCode())
.build());
}
我们必须在入站网关级别处理下游错误。为此 Spring 集成建议 errorChannel
功能。
httpProxyErrorFlow
提供了一些关于此事的逻辑。首先我们知道 errorChannel
的消息是 ErrorMessage
而它的 payload
是 MessagingException
- 作为在 [=19 中包装 HttpClientErrorException
的结果=].因此,在 .transform()
中,我们深入到所需的异常,在 .handle()
中,我们基于 HttpClientErrorException
内容构建了一条新消息。
HttpRequestHandlingMessagingGateway
能够正确处理此类消息并为响应设置所需的状态代码:
protected final Object setupResponseAndConvertReply(ServletServerHttpResponse response, Message<?> replyMessage) {
getHeaderMapper().fromHeaders(replyMessage.getHeaders(), response.getHeaders());
HttpStatus httpStatus = this.resolveHttpStatusFromHeaders(replyMessage.getHeaders());
if (httpStatus != null) {
response.setStatusCode(httpStatus);
}
我有一个入站 http 网关,其传入消息被传递到出站 http 网关(使用集成 java dsl)。
当出站网关响应的 http 状态为 200 时,出站响应会按预期返回到入站网关的调用方。
但是,当出站网关响应特定的客户端错误(例如 423 锁定或 403 禁止)时,入站网关的调用方会收到 500 和包含字符串异常的正文消息。
我了解这是因为 SI 将出站 http 错误作为异常处理。但在我的例子中,我需要通过错误状态 和 将出站响应附带的响应主体返回给入站网关的调用者,以获取特定的错误代码。我该怎么做?
我们将这种情况称为 HTTP 代理,并且有一些关于此事的测试用例:https://github.com/spring-projects/spring-integration/blob/master/spring-integration-http/src/test/java/org/springframework/integration/http/dsl/HttpDslTests.java
我刚刚做了一些调查,这是你需要的:
IntegrationFlows
.from(Http.inboundGateway("/service")
.requestMapping(r -> r.params("name"))
.errorChannel("httpProxyErrorFlow.input"))
...
@Bean
public IntegrationFlow httpProxyErrorFlow() {
return f -> f
.transform(Throwable::getCause)
.<HttpClientErrorException>handle((p, h) ->
MessageBuilder.withPayload(p.getResponseBodyAsString())
.setHeader(HttpHeaders.STATUS_CODE, p.getStatusCode())
.build());
}
我们必须在入站网关级别处理下游错误。为此 Spring 集成建议 errorChannel
功能。
httpProxyErrorFlow
提供了一些关于此事的逻辑。首先我们知道 errorChannel
的消息是 ErrorMessage
而它的 payload
是 MessagingException
- 作为在 [=19 中包装 HttpClientErrorException
的结果=].因此,在 .transform()
中,我们深入到所需的异常,在 .handle()
中,我们基于 HttpClientErrorException
内容构建了一条新消息。
HttpRequestHandlingMessagingGateway
能够正确处理此类消息并为响应设置所需的状态代码:
protected final Object setupResponseAndConvertReply(ServletServerHttpResponse response, Message<?> replyMessage) {
getHeaderMapper().fromHeaders(replyMessage.getHeaders(), response.getHeaders());
HttpStatus httpStatus = this.resolveHttpStatusFromHeaders(replyMessage.getHeaders());
if (httpStatus != null) {
response.setStatusCode(httpStatus);
}