Closed valuetodays closed 4 years ago
You could check the Content-Length
or Transfer-Encoding
headers using the getHeaders()
method. That method will retrieve the headers from the original response.
I tried just now, the Content-Length
is -1 when downstream returns a json, and it is 0 when get null from downstream.
I checked the javadoc in org.springframework.http.HttpHeaders#getContentLength, it said:
/**
* Return the length of the body in bytes, as specified by the
* {@code Content-Length} header.
* <p>Returns -1 when the content-length is unknown.
*/
Why Content-Length is -1 when downstream return a json? Is there something wrong with downstream? My downstream is just a springboot application with springcloud-config and eureka configured. SpringBoot Version: 2.1.6.RELEASE SpringCloud Version: Greenwich.RELEASE
I checked many times and got the following results from a SpingBoot application.
Content-Length
is missing and Transfer-Encoding
is "chunked"Content-Length
is 0 and Transfer-Encoding
is missingThe following code snippets works for me, but I am not sure whether it is exact enough .
ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(exchange.getResponse()) {
@Override
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
if (body instanceof Flux) {
Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body;
String transferEncoding = this.getDelegate().getHeaders().getFirst(HttpHeaders.TRANSFER_ENCODING);
long contentLength = this.getDelegate().getHeaders().getContentLength();
// when "Transfer-Encoding" is null && "Content-Length" is 0
if (null == transferEncoding && 0 == contentLength) {
// do something
}
}
return super.writeWith(body);
}
};
@billysAnna in case you don't trust those headers - you can read the body and get it's lenght
@kkocel I tried, but the following code snippets not work.
Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body;
Flux<DataBuffer> respDataBuffer = fluxBody.buffer().map(dataBuffers -> {
// when get null from downstream, cannot go here
});
So, I want to know whether fuluxBody
can indicate that or not.
switchOnEmpty()
?
Please take a look at the snippet below to work with those data buffers.
Try to always use the DataBufferUtils
class since those util methods also take retaining/releasing byte buffers into account.
I didn't test this prior to posting it since I don't know your use case but this might point you in the right direction.
Hope this helps!
ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(exchange.getResponse()) {
@Override
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
Mono<DataBuffer> newBody = DataBufferUtils.join(body)
.map(content -> {
// Using readPosition() and readableByteCount() you can determine if the body is empty.
// You can also take the HTTP headers into account again.
// In case null and empty should behave the same you could return Mono.empty() here.
})
.switchIfEmpty(/* Provide a fallback in case there was no content. */)
return super.writeWith(newBody);
}
};
@TYsewyn @spencergibb I tried what you said. That works for me.
Still another way is to let the downstream return a wrapped object instead of a simple one. if the downstream return a User object, tell them to return Rest
public class Rest<T> {
private int errorCode;
private String errorMsg;
private T data;
// getter and setter ....
}
Thus, an api named /user/findById/{id}
will return Rest object even the user with specified id not exists.,
which will always response a non-null object back to gateway. And I do not face the question any more. :)
Thx.