spring-cloud / spring-cloud-openfeign

Support for using OpenFeign in Spring Cloud apps
Apache License 2.0
1.17k stars 756 forks source link

Custom HTTP codes are not supported #1010

Closed pasichenko closed 2 months ago

pasichenko commented 3 months ago

Describe the bug Spring Cloud Openfeign version: 4.1.0 Using HttpStatus.valueof(int) in SpringDecoder and ResponseEntityDecoder causes an exception to be thrown if using HTTP codes that are not listed in HttpStatus.

Caused by: java.lang.IllegalArgumentException: No matching constant for [245]
    at org.springframework.http.HttpStatus.valueOf(HttpStatus.java:515) ~[spring-web-6.1.5.jar:6.1.5]
    at org.springframework.cloud.openfeign.support.SpringDecoder$FeignResponseAdapter.getStatusCode(SpringDecoder.java:86) ~[spring-cloud-openfeign-core-4.1.0.jar:4.1.0]
    at org.springframework.cloud.openfeign.support.SpringDecoder$FeignResponseAdapter.getStatusCode(SpringDecoder.java:76) ~[spring-cloud-openfeign-core-4.1.0.jar:4.1.0]
    at org.springframework.web.client.ClientHttpResponseDecorator.getStatusCode(ClientHttpResponseDecorator.java:55) ~[spring-web-6.1.5.jar:6.1.5]
    at org.springframework.web.client.IntrospectingClientHttpResponse.hasMessageBody(IntrospectingClientHttpResponse.java:60) ~[spring-web-6.1.5.jar:6.1.5]
    at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:90) ~[spring-web-6.1.5.jar:6.1.5]
    at org.springframework.cloud.openfeign.support.SpringDecoder.decode(SpringDecoder.java:70) ~[spring-cloud-openfeign-core-4.1.0.jar:4.1.0]
    at org.springframework.cloud.openfeign.support.ResponseEntityDecoder.decode(ResponseEntityDecoder.java:53) ~[spring-cloud-openfeign-core-4.1.0.jar:4.1.0]
    at feign.optionals.OptionalDecoder.decode(OptionalDecoder.java:36) ~[feign-core-13.1.jar:na]

Sample producer application:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@SpringBootApplication
public class ProducerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProducerApplication.class, args);
    }

    @GetMapping("/api/v1/entity")
    public ResponseEntity<String> getSomeEntity() {
        return ResponseEntity.status(245)
                .body("Producer - 245 status");
    }
}

consumer application:

import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.http.ResponseEntity;

@SpringBootApplication
@EnableFeignClients
@RequiredArgsConstructor
public class ConsumerApplication implements CommandLineRunner {
    private static final Logger log = LoggerFactory.getLogger(ConsumerApplication.class);
    private final ProducerApiFeignClient producerClient;

    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class, args);
    }

    @Override
    public void run(String... args) {
        ResponseEntity<String> someEntity = producerClient.someEntity();
        log.info("Produce API - Http status code [{}]", someEntity.getStatusCode());
        log.info("Produce API - Body [{}]", someEntity.getBody());
    }
}
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;

@FeignClient(value = "producer-api-client", url = "http://localhost:8081")
public interface ProducerApiFeignClient {
    @GetMapping("/api/v1/entity")
    ResponseEntity<String> someEntity();
}
OlgaMaciaszek commented 2 months ago

Hello, @pasichenko. Thanks for reporting the issue. Makes sense.