Skip to content

Allow conditional handling of 404 with HTTP Interface clients #32105

Open
@floriandreher

Description

@floriandreher

With feign it was possible to easily map 404 exceptions to null via the dismiss404 functionality. It seems like, that there is no easy and convenient way to do that wie http interfaces and restclient.

My current workaround is to write my own implementation of the HttpExchangeAdapter interface.

public class MyExchangeAdapter implements HttpExchangeAdapter {

    private final HttpExchangeAdapter delegate;

    public MyExchangeAdapter(HttpExchangeAdapter delegate) {
        this.delegate = delegate;
    }

    public static HttpExchangeAdapter create(RestClient client) {
        return new MyExchangeAdapter(RestClientAdapter.create(client));
    }

    @Override
    public boolean supportsRequestAttributes() {
        return delegate.supportsRequestAttributes();
    }

    @Override
    public void exchange(HttpRequestValues requestValues) {
        delegate.exchange(requestValues);
    }

    @Override
    public HttpHeaders exchangeForHeaders(HttpRequestValues requestValues) {
        return delegate.exchangeForHeaders(requestValues);
    }

    @Override
    public <T> T exchangeForBody(HttpRequestValues requestValues, ParameterizedTypeReference<T> bodyType) {
        return exchangeForEntity(requestValues, bodyType)
            .getBody();
    }

    @Override
    public ResponseEntity<Void> exchangeForBodilessEntity(HttpRequestValues requestValues) {
        return delegate.exchangeForBodilessEntity(requestValues);
    }

    @Override
    public <T> ResponseEntity<T> exchangeForEntity(HttpRequestValues requestValues, ParameterizedTypeReference<T> bodyType) {
        try {
            return delegate.exchangeForEntity(requestValues, bodyType);
        } catch (HttpClientErrorException.NotFound ex) {
            return ResponseEntity.notFound().build();
        }
    }
}

and configure my client something like:

@Configuration
public class MyClientConfig {

    @Bean
    public MyClient myClient(RestClient.Builder restClientBuilder) {
        var client = restClientBuilder
           .defaultStatusHandler(this::isError, (request, response) -> {
            })
            .build();
        var httpServiceProxyFactory = HttpServiceProxyFactory
            .builderFor(MyExchangeAdapter.create(client))
            .build();

        return httpServiceProxyFactory.createClient(MyClient.class);
    }

    public boolean isError(HttpStatusCode statusCode) {
        return statusCode.isError() && statusCode != HttpStatus.NOT_FOUND;
    }
}

Am i missing a more elegant and easy way or do you plan to provide some dismiss404 mechanism?

Thanks!

Metadata

Metadata

Assignees

Labels

in: webIssues in web modules (web, webmvc, webflux, websocket)type: enhancementA general enhancement

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions