简体   繁体   中英

Spring integration flow respond with HTTP 400

I have a spring integration flow that expects a "routingkey" message header. If this is not present I'd like to send a HTTP 400 response back to the client. How can I do that? Below you will see the determineRoutingKey method is where I can determine whether the routing key was passed as a header.

@Bean
public IntegrationFlow webToRabbit(RabbitTemplate amqpTemplate)
{
    return IntegrationFlows
            .from
            (
                Http.inboundGateway("/tunnel")
                    .replyTimeout(Integer.valueOf(timeout))
                    .mappedRequestHeaders("*")
                    .mappedResponseHeaders("*")
            )
            .log()
            .handle
            (
                Amqp.outboundGateway(amqpTemplate)
                    .exchangeName(exchangeName)
                    .routingKeyFunction(f->determineRoutingKey(f))
                    .mappedRequestHeaders("*")
                    .mappedReplyHeaders("*")
            )
            .log()
            .bridge(null)
            .get();
}

private String determineRoutingKey(Message<?> message) 
{
    MessageHeaders headers = message.getHeaders();
    if(headers.containsKey(HEADER_ROUTINGKEY))
    {
        String routingKey = Objects.toString(headers.get(HEADER_ROUTINGKEY));
        log.debug("Using routing key: " + routingKey);
        return routingKey;
    }
    else
    {
        log.error("Headers found: " + Objects.toString(headers));

        //Here I get an exception stating that MessageHeaaders is immutable
        message.getHeaders().put(HttpHeaders.STATUS_CODE, HttpStatus.BAD_REQUEST);
        return null;
    }
}

Thanks in advance for the help.

There is a logic like:

private HttpStatus resolveHttpStatusFromHeaders(MessageHeaders headers) {
    Object httpStatusFromHeader = headers.get(org.springframework.integration.http.HttpHeaders.STATUS_CODE);
    return buildHttpStatus(httpStatusFromHeader);
}

So, what you need is just regular (string with error message?) reply and an appropriate HttpStatus.BAD_REQUEST as a http_statusCode header.

No reason in any exceptions.

UPDATE

Since you are in the middle of the flow and it is still far away from the reply, you can stick with that exception approach.

What you have to do there to return proper 400 response is an errorChannel on the Http.inboundGateway() and some simple transformer to returns a Message with an appropriate HttpHeaders.STATUS_CODE header:

Http.inboundGateway("/tunnel")
    .errorChannel("httpErrorFlow.input")
...

@Bean
public IntegrationFlow httpErrorFlow() {
    return f -> f
            .<RuntimeException, Message<?>>transform(payload -> {
                if (payload.getCause() instanceof MyRoutingKeyException) {
                    return MessageBuilder.withPayload("Bad routing key")
                            .setHeader(HttpHeaders.STATUS_CODE, HttpStatus.BAD_REQUEST)
                            .build();
                }
                throw payload;
            });
}

But again: you can't just throw an exception.

That is

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM