Add compressionState getter to the HttpClientResponse API.

Bug: dartbug.com/36971
Change-Id: I7dc0b48fe8eddb2f49a73efb9c4c6aba1233179b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/102800
Commit-Queue: Todd Volkert <tvolkert@google.com>
Reviewed-by: Zach Anderson <zra@google.com>
This commit is contained in:
Todd Volkert 2019-05-30 21:57:35 +00:00 committed by commit-bot@chromium.org
parent c4a1ca903f
commit aa2ce7cfbf
3 changed files with 75 additions and 7 deletions

View file

@ -31,8 +31,17 @@ class B<X> extends A<void Function(X)> {};
cookie values to be the empty string (Issue [35804][]) and not stripping
double quotes from the value (Issue [33327][]) in accordance with RFC 6265.
[33327]: https://github.com/dart-lang/sdk/issues/33327
[35804]: https://github.com/dart-lang/sdk/issues/35804
[33327]: https://github.com/dart-lang/sdk/issues/33327
[35804]: https://github.com/dart-lang/sdk/issues/35804
* The `HttpClientResponse` interface has been extended with the addition of a
new `compressionState` getter, which specifies whether the body of a
response was compressed when it was received and whether it has been
automatically uncompressed via `HttpClient.autoUncompress`.
* **Breaking change**: For those implementing the `HttpClientResponse`
interface, this is a breaking change, as implementing classes will need to
implement the new getter.
### Dart VM

View file

@ -1958,6 +1958,13 @@ abstract class HttpClientResponse implements Stream<List<int>> {
*/
int get contentLength;
/// The compression state of the response.
///
/// This specifies whether the response bytes were compressed when they were
/// received across the wire and whether callers will receive compressed
/// or uncompressed bytes when they listed to this response's byte stream.
HttpClientResponseCompressionState get compressionState;
/**
* Gets the persistent connection state returned by the server.
*
@ -2037,6 +2044,48 @@ abstract class HttpClientResponse implements Stream<List<int>> {
HttpConnectionInfo get connectionInfo;
}
/// Enum that specifies the compression state of the byte stream of an
/// [HttpClientResponse].
///
/// The values herein allow callers to answer the following questions as they
/// pertain to an [HttpClientResponse]:
///
/// * Can the value of the response's `Content-Length` HTTP header be trusted?
/// * Does the caller need to manually decompress the response's byte stream?
///
/// This enum is accessed via the [HttpClientResponse.compressionState] value.
enum HttpClientResponseCompressionState {
/// The body of the HTTP response was received and remains in an uncompressed
/// state.
///
/// In this state, the value of the `Content-Length` HTTP header, if
/// specified (non-negative), should match the number of bytes produced by
/// the response's byte stream.
notCompressed,
/// The body of the HTTP response was originally compressed, but by virtue of
/// the [HttpClient.autoUncompress] configuration option, it has been
/// automatically uncompressed.
///
/// HTTP headers are not modified, so when a response has been uncompressed
/// in this way, the value of the `Content-Length` HTTP header cannot be
/// trusted, as it will contain the compressed content length, whereas the
/// stream of bytes produced by the response will contain uncompressed bytes.
decompressed,
/// The body of the HTTP response contains compressed bytes.
///
/// In this state, the value of the `Content-Length` HTTP header, if
/// specified (non-negative), should match the number of bytes produced by
/// the response's byte stream.
///
/// If the caller wishes to manually uncompress the body of the response,
/// it should consult the value of the `Content-Encoding` HTTP header to see
/// what type of compression has been applied. See
/// <https://tools.ietf.org/html/rfc2616#section-14.11> for more information.
compressed,
}
abstract class HttpClientCredentials {}
/**

View file

@ -292,17 +292,28 @@ class _HttpClientResponse extends _HttpInboundMessage
// The HttpClientRequest of this response.
final _HttpClientRequest _httpRequest;
// Whether this response is configured to auto uncompress.
final bool autoUncompress;
// The compression state of this response.
final HttpClientResponseCompressionState compressionState;
_HttpClientResponse(
_HttpIncoming _incoming, this._httpRequest, this._httpClient)
: autoUncompress = _httpClient.autoUncompress,
: compressionState = _getCompressionState(_httpClient, _incoming.headers),
super(_incoming) {
// Set uri for potential exceptions.
_incoming.uri = _httpRequest.uri;
}
static HttpClientResponseCompressionState _getCompressionState(
_HttpClient httpClient, _HttpHeaders headers) {
if (headers.value(HttpHeaders.contentEncodingHeader) == "gzip") {
return httpClient.autoUncompress
? HttpClientResponseCompressionState.decompressed
: HttpClientResponseCompressionState.compressed;
} else {
return HttpClientResponseCompressionState.notCompressed;
}
}
int get statusCode => _incoming.statusCode;
String get reasonPhrase => _incoming.reasonPhrase;
@ -381,8 +392,7 @@ class _HttpClientResponse extends _HttpInboundMessage
return new Stream<List<int>>.empty().listen(null, onDone: onDone);
}
Stream<List<int>> stream = _incoming;
if (autoUncompress &&
headers.value(HttpHeaders.contentEncodingHeader) == "gzip") {
if (compressionState == HttpClientResponseCompressionState.decompressed) {
stream = stream.transform(gzip.decoder);
}
return stream.listen(onData,