Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 730
Josh Chappelle Avatar asked Apr 25 '26 13:04

Josh Chappelle


1 Answers

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

like image 84
Artem Bilan Avatar answered Apr 27 '26 02:04

Artem Bilan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!