|
|
|
@ -16,6 +16,7 @@ |
|
|
|
|
|
|
|
|
|
|
|
package org.springframework.web.client; |
|
|
|
package org.springframework.web.client; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import java.io.EOFException; |
|
|
|
import java.io.IOException; |
|
|
|
import java.io.IOException; |
|
|
|
import java.io.InputStream; |
|
|
|
import java.io.InputStream; |
|
|
|
import java.io.PushbackInputStream; |
|
|
|
import java.io.PushbackInputStream; |
|
|
|
@ -34,7 +35,6 @@ import org.springframework.http.client.ClientHttpResponse; |
|
|
|
* @author Brian Clozel |
|
|
|
* @author Brian Clozel |
|
|
|
* @author Rossen Stoyanchev |
|
|
|
* @author Rossen Stoyanchev |
|
|
|
* @since 4.1.5 |
|
|
|
* @since 4.1.5 |
|
|
|
* @see <a href="https://tools.ietf.org/html/rfc7230#section-3.3.3">RFC 7230 Section 3.3.3</a> |
|
|
|
|
|
|
|
*/ |
|
|
|
*/ |
|
|
|
class IntrospectingClientHttpResponse extends ClientHttpResponseDecorator { |
|
|
|
class IntrospectingClientHttpResponse extends ClientHttpResponseDecorator { |
|
|
|
|
|
|
|
|
|
|
|
@ -47,14 +47,18 @@ class IntrospectingClientHttpResponse extends ClientHttpResponseDecorator { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Indicates whether the response has a message body. |
|
|
|
* Indicates whether the response might have a message body. |
|
|
|
* <p>Implementation returns {@code false} for: |
|
|
|
* <p>Implementation returns {@code false} for: |
|
|
|
* <ul> |
|
|
|
* <ul> |
|
|
|
* <li>a response status of {@code 1XX}, {@code 204} or {@code 304}</li> |
|
|
|
* <li>a response status of {@code 1XX}, {@code 204} or {@code 304}</li> |
|
|
|
* <li>a {@code Content-Length} header of {@code 0}</li> |
|
|
|
* <li>a {@code Content-Length} header of {@code 0}</li> |
|
|
|
* </ul> |
|
|
|
* </ul> |
|
|
|
* @return {@code true} if the response has a message body, {@code false} otherwise |
|
|
|
* <p>In other cases, the server could use a {@code Transfer-Encoding} header or just |
|
|
|
|
|
|
|
* write the body and close the response. Reading the message body is then the only way |
|
|
|
|
|
|
|
* to check for the presence of a body. |
|
|
|
|
|
|
|
* @return {@code true} if the response might have a message body, {@code false} otherwise |
|
|
|
* @throws IOException in case of I/O errors |
|
|
|
* @throws IOException in case of I/O errors |
|
|
|
|
|
|
|
* @see <a href="https://tools.ietf.org/html/rfc7230#section-3.3.3">RFC 7230 Section 3.3.3</a> |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public boolean hasMessageBody() throws IOException { |
|
|
|
public boolean hasMessageBody() throws IOException { |
|
|
|
HttpStatusCode statusCode = getStatusCode(); |
|
|
|
HttpStatusCode statusCode = getStatusCode(); |
|
|
|
@ -62,10 +66,7 @@ class IntrospectingClientHttpResponse extends ClientHttpResponseDecorator { |
|
|
|
statusCode == HttpStatus.NOT_MODIFIED) { |
|
|
|
statusCode == HttpStatus.NOT_MODIFIED) { |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
if (getHeaders().getContentLength() == 0) { |
|
|
|
return getHeaders().getContentLength() != 0; |
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
@ -73,6 +74,7 @@ class IntrospectingClientHttpResponse extends ClientHttpResponseDecorator { |
|
|
|
* <p>Implementation tries to read the first bytes of the response stream: |
|
|
|
* <p>Implementation tries to read the first bytes of the response stream: |
|
|
|
* <ul> |
|
|
|
* <ul> |
|
|
|
* <li>if no bytes are available, the message body is empty</li> |
|
|
|
* <li>if no bytes are available, the message body is empty</li> |
|
|
|
|
|
|
|
* <li>if an {@link EOFException} is thrown, the body is considered empty</li> |
|
|
|
* <li>otherwise it is not empty and the stream is reset to its start for further reading</li> |
|
|
|
* <li>otherwise it is not empty and the stream is reset to its start for further reading</li> |
|
|
|
* </ul> |
|
|
|
* </ul> |
|
|
|
* @return {@code true} if the response has a zero-length message body, {@code false} otherwise |
|
|
|
* @return {@code true} if the response has a zero-length message body, {@code false} otherwise |
|
|
|
@ -85,26 +87,31 @@ class IntrospectingClientHttpResponse extends ClientHttpResponseDecorator { |
|
|
|
if (body == null) { |
|
|
|
if (body == null) { |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
if (body.markSupported()) { |
|
|
|
try { |
|
|
|
body.mark(1); |
|
|
|
if (body.markSupported()) { |
|
|
|
if (body.read() == -1) { |
|
|
|
body.mark(1); |
|
|
|
return true; |
|
|
|
if (body.read() == -1) { |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else { |
|
|
|
|
|
|
|
body.reset(); |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
else { |
|
|
|
body.reset(); |
|
|
|
this.pushbackInputStream = new PushbackInputStream(body); |
|
|
|
return false; |
|
|
|
int b = this.pushbackInputStream.read(); |
|
|
|
|
|
|
|
if (b == -1) { |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else { |
|
|
|
|
|
|
|
this.pushbackInputStream.unread(b); |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
catch (EOFException exc) { |
|
|
|
this.pushbackInputStream = new PushbackInputStream(body); |
|
|
|
return true; |
|
|
|
int b = this.pushbackInputStream.read(); |
|
|
|
|
|
|
|
if (b == -1) { |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else { |
|
|
|
|
|
|
|
this.pushbackInputStream.unread(b); |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|