Skip to content

Commit

Permalink
Add compressionState getter to the HttpClientResponse API.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
tvolkert authored and commit-bot@chromium.org committed May 30, 2019
1 parent c4a1ca9 commit aa2ce7c
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 7 deletions.
13 changes: 11 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
49 changes: 49 additions & 0 deletions sdk/lib/_http/http.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down Expand Up @@ -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 {}

/**
Expand Down
20 changes: 15 additions & 5 deletions sdk/lib/_http/http_impl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit aa2ce7c

Please sign in to comment.