response.dart 3.39 KB
Newer Older
1 2 3 4
// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

5
import 'dart:async';
6
import 'dart:convert';
7
import 'dart:typed_data';
8

9
import 'package:http_parser/http_parser.dart';
10

11 12 13 14
import 'base_request.dart';
import 'base_response.dart';
import 'streamed_response.dart';
import 'utils.dart';
15

16 17 18
/// An HTTP response where the entire response body is known in advance.
class Response extends BaseResponse {
  /// The bytes comprising the body of this response.
19
  final Uint8List bodyBytes;
20

21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
  /// Creates a new HTTP response with a string body.
  Response(
      String body,
      int statusCode,
      {BaseRequest request,
       Map<String, String> headers: const <String, String>{},
       bool isRedirect: false,
       bool persistentConnection: true,
       String reasonPhrase})
    : this.bytes(
        _encodingForHeaders(headers).encode(body),
        statusCode,
        request: request,
        headers: headers,
        isRedirect: isRedirect,
        persistentConnection: persistentConnection,
        reasonPhrase: reasonPhrase);
38

39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
  /// Create a new HTTP response with a byte array body.
  Response.bytes(
      List<int> bodyBytes,
      int statusCode,
      {BaseRequest request,
       Map<String, String> headers: const <String, String>{},
       bool isRedirect: false,
       bool persistentConnection: true,
       String reasonPhrase})
    : bodyBytes = toUint8List(bodyBytes),
      super(
        statusCode,
        contentLength: bodyBytes.length,
        request: request,
        headers: headers,
        isRedirect: isRedirect,
        persistentConnection: persistentConnection,
        reasonPhrase: reasonPhrase);
57

58 59 60 61 62 63 64
  /// The body of the response as a string. This is converted from [bodyBytes]
  /// using the `charset` parameter of the `Content-Type` header field, if
  /// available. If it's unavailable or if the encoding name is unknown,
  /// [LATIN1] is used by default, as per [RFC 2616][].
  ///
  /// [RFC 2616]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html
  String get body => _encodingForHeaders(headers).decode(bodyBytes);
65

66 67 68 69 70 71 72 73 74 75 76 77 78
  /// Creates a new HTTP response by waiting for the full body to become
  /// available from a [StreamedResponse].
  static Future<Response> fromStream(StreamedResponse response) {
    return response.stream.toBytes().then((List<int> body) {
      return new Response.bytes(
          body,
          response.statusCode,
          request: response.request,
          headers: response.headers,
          isRedirect: response.isRedirect,
          persistentConnection: response.persistentConnection,
          reasonPhrase: response.reasonPhrase);
    });
79 80 81
  }
}

82 83 84 85 86 87 88 89 90 91
/// Returns the encoding to use for a response with the given headers. This
/// defaults to [LATIN1] if the headers don't specify a charset or
/// if that charset is unknown.
Encoding _encodingForHeaders(Map<String, String> headers) =>
  encodingForCharset(_contentTypeForHeaders(headers).parameters['charset']);

/// Returns the [MediaType] object for the given headers's content-type.
///
/// Defaults to `application/octet-stream`.
MediaType _contentTypeForHeaders(Map<String, String> headers) {
92
  String contentType = headers['content-type'];
93 94
  if (contentType != null) return new MediaType.parse(contentType);
  return new MediaType("application", "octet-stream");
95
}