Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WebClient's handling of empty bodies seems broken [SPR-15679] #20238

Closed
spring-issuemaster opened this issue Jun 18, 2017 · 1 comment

Comments

Projects
None yet
2 participants
@spring-issuemaster
Copy link
Collaborator

commented Jun 18, 2017

Johannes Edmeier opened SPR-15679 and commented

When the WebClient retrieves an response without content (header content-length: 0 and without content-type header ) I would expect following things:

  1. when calling exchange() and doing ClientResponse#bodyToMono(Void.class) I expect that an empty Mono (that just completes) for the body is returned
  2. when calling retrieve().toEntity(Void.class) I expect a Mono with a ResponseEntity instance whose hasBody() returns false.

Both is currently not possible and throws an UnsupportedMediaTypeException

Tests:

  @Test
    public void nocontent_entity() {
        Mono<ResponseEntity<Void>> responseEntity = WebClient.create("http://localhost:8080")
                                                             .post()
                                                             .uri("/nocontent")
                                                             .retrieve()
                                                             .toEntity(Void.class);

        StepVerifier.create(responseEntity).assertNext(r -> {
            assertThat(r.hasBody()).isFalse();
            assertThat(r.getStatusCode().is2xxSuccessful()).isTrue();
        }).verifyComplete();
    }

    @Test
    public void nocontent_response() {
        Mono<ClientResponse> response = WebClient.create("http://localhost:8080").post().uri("/nocontent").exchange();

        StepVerifier.create(response).assertNext(r -> {
            assertThat(r.statusCode().is2xxSuccessful()).isTrue();
            StepVerifier.create(r.bodyToMono(Void.class)).verifyComplete();
        }).verifyComplete();
    }

Application

@SpringBootApplication
@RestController
public class WebfluxApplication {

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

	@PostMapping(path="/nocontent")
	public Mono<Void> nocontent() {
		return Mono.empty();
	}
}
java.lang.AssertionError: expectation "expectComplete" failed (expected: onComplete(); actual: onError(org.springframework.web.reactive.function.UnsupportedMediaTypeException: Content type 'application/octet-stream' not supported))

	at reactor.test.DefaultStepVerifierBuilder.failPrefix(DefaultStepVerifierBuilder.java:2114)
	at reactor.test.DefaultStepVerifierBuilder.fail(DefaultStepVerifierBuilder.java:2110)
	at reactor.test.DefaultStepVerifierBuilder.lambda$expectComplete$3(DefaultStepVerifierBuilder.java:199)
	at reactor.test.DefaultStepVerifierBuilder$SignalEvent.test(DefaultStepVerifierBuilder.java:1855)
	at reactor.test.DefaultStepVerifierBuilder$DefaultVerifySubscriber.onSignal(DefaultStepVerifierBuilder.java:1241)
	at reactor.test.DefaultStepVerifierBuilder$DefaultVerifySubscriber.onExpectation(DefaultStepVerifierBuilder.java:1186)
	at reactor.test.DefaultStepVerifierBuilder$DefaultVerifySubscriber.onError(DefaultStepVerifierBuilder.java:858)
	at reactor.core.publisher.Operators.error(Operators.java:195)
	at reactor.core.publisher.MonoError.subscribe(MonoError.java:51)
	at reactor.test.DefaultStepVerifierBuilder$DefaultStepVerifier.verify(DefaultStepVerifierBuilder.java:665)
	at reactor.test.DefaultStepVerifierBuilder$DefaultStepVerifier.verify(DefaultStepVerifierBuilder.java:639)
	at reactor.test.DefaultStepVerifierBuilder.verifyComplete(DefaultStepVerifierBuilder.java:508)
	at com.example.webflux.WebfluxApplicationTests.lambda$nocontent_response$1(WebfluxApplicationTests.java:46)
	at reactor.test.DefaultStepVerifierBuilder.lambda$consumeNextWith$1(DefaultStepVerifierBuilder.java:157)
	at reactor.test.DefaultStepVerifierBuilder$SignalEvent.test(DefaultStepVerifierBuilder.java:1855)
	at reactor.test.DefaultStepVerifierBuilder$DefaultVerifySubscriber.onSignal(DefaultStepVerifierBuilder.java:1241)
	at reactor.test.DefaultStepVerifierBuilder$DefaultVerifySubscriber.onExpectation(DefaultStepVerifierBuilder.java:1186)
	at reactor.test.DefaultStepVerifierBuilder$DefaultVerifySubscriber.onNext(DefaultStepVerifierBuilder.java:875)
	at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:108)
	at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:170)
	at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:108)
	at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:108)
	at reactor.core.publisher.FluxRetryPredicate$RetryPredicateSubscriber.onNext(FluxRetryPredicate.java:79)
	at reactor.core.publisher.MonoCreate$DefaultMonoSink.success(MonoCreate.java:122)
	at reactor.ipc.netty.channel.PooledClientContextHandler.fireContextActive(PooledClientContextHandler.java:84)
	at reactor.ipc.netty.http.client.HttpClientOperations.onInboundNext(HttpClientOperations.java:542)
	at reactor.ipc.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:125)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
	at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:310)
	at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:284)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1334)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:926)
	at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:134)
	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:644)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:579)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:496)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:458)
	at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:858)
	at java.lang.Thread.run(Thread.java:745)
	Suppressed: org.springframework.web.reactive.function.UnsupportedMediaTypeException: Content type 'application/octet-stream' not supported
		at org.springframework.web.reactive.function.BodyExtractors.lambda$readWithMessageReaders$16(BodyExtractors.java:237)
		at java.util.Optional.orElseGet(Optional.java:267)
		at org.springframework.web.reactive.function.BodyExtractors.readWithMessageReaders(BodyExtractors.java:233)
		at org.springframework.web.reactive.function.BodyExtractors.lambda$toMono$1(BodyExtractors.java:92)
		at org.springframework.web.reactive.function.client.DefaultClientResponse.body(DefaultClientResponse.java:78)
		at org.springframework.web.reactive.function.client.DefaultClientResponse.bodyToMono(DefaultClientResponse.java:98)
		... 34 more

Affects: 5.0 RC2

Issue Links:

  • #20260 WebClient fails to transform empty json array to emtpy flux ("is duplicated by")
@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Jun 20, 2017

Arjen Poutsma commented

Fixed in 50fc8f4

Thanks for reporting this issue!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.