Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 library request; | |
| 6 | |
| 7 import 'dart:io'; | |
| 8 import 'dart:scalarlist'; | |
| 9 import 'dart:uri'; | |
| 10 | |
| 11 import 'base_request.dart'; | |
| 12 import 'utils.dart'; | |
| 13 | |
| 14 /// An HTTP request where the entire request body is known in advance. | |
| 15 class Request extends BaseRequest { | |
| 16 /// The size of the request body, in bytes. This is calculated from | |
| 17 /// [bodyBytes]. | |
| 18 /// | |
| 19 /// The content length cannot be set for [Request], since it's automatically | |
| 20 /// calculated from [bodyBytes]. | |
| 21 int get contentLength => bodyBytes.length; | |
| 22 | |
| 23 set contentLength(int value) { | |
| 24 throw new UnsupportedError("Cannot set the contentLength property of " | |
| 25 "non-streaming Request objects."); | |
| 26 } | |
| 27 | |
| 28 /// The default encoding to use when converting between [bodyBytes] and | |
| 29 /// [body]. This is only used if [encoding] hasn't been manually set and if | |
| 30 /// the content-type header has no encoding information. | |
| 31 Encoding _defaultEncoding; | |
| 32 | |
| 33 /// The encoding used for the request. This encoding is used when converting | |
| 34 /// between [bodyBytes] and [body]. | |
| 35 /// | |
| 36 /// If the request has a `Content-Type` header and that header has a `charset` | |
| 37 /// parameter, that parameter's value is used as the encoding. Otherwise, if | |
| 38 /// [encoding] has been set manually, that encoding is used. If that hasn't | |
| 39 /// been set either, this defaults to [Encoding.UTF_8]. | |
| 40 /// | |
| 41 /// If the `charset` parameter's value is not a known [Encoding], reading this | |
| 42 /// will throw an [UnsupportedError]. | |
|
Bob Nystrom
2012/10/31 01:17:44
UnsupportedError feels wrong here. Probably Format
nweiz
2012/10/31 18:20:59
Done.
| |
| 43 /// | |
| 44 /// If the request has a `Content-Type` header, setting this will set the | |
| 45 /// charset parameter on that header. | |
| 46 Encoding get encoding { | |
| 47 if (_contentType == null || _contentType.charset == null) { | |
| 48 return _defaultEncoding; | |
| 49 } | |
| 50 return requiredEncodingForCharset(_contentType.charset); | |
| 51 } | |
| 52 | |
| 53 set encoding(Encoding value) { | |
| 54 _checkFinalized(); | |
| 55 _defaultEncoding = value; | |
| 56 var contentType = _contentType; | |
| 57 if (contentType != null) { | |
| 58 contentType.charset = value.name; | |
| 59 _contentType = contentType; | |
| 60 } | |
| 61 } | |
| 62 | |
| 63 // TODO(nweiz): make this return a read-only view | |
| 64 /// The bytes comprising the body of the request. This is converted to and | |
| 65 /// from [body] using [encoding]. | |
| 66 /// | |
| 67 /// This list should only be set, not be modified in place. | |
| 68 Uint8List get bodyBytes => _bodyBytes; | |
| 69 Uint8List _bodyBytes; | |
| 70 | |
| 71 set bodyBytes(List<int> value) { | |
| 72 _checkFinalized(); | |
| 73 _bodyBytes = uint8List(value); | |
| 74 } | |
| 75 | |
| 76 /// The body of the request as a string. This is converted to and from | |
| 77 /// [bodyBytes] using [encoding]. | |
| 78 /// | |
| 79 /// When this is set, if the request does not yet have a `Content-Type` | |
| 80 /// header, one will be added with the type `text/plain`. Then the `charset` | |
| 81 /// parameter of the `Content-Type` header (whether new or pre-existing) will | |
| 82 /// be set to [encoding] if it wasn't already set. | |
| 83 String get body => decodeString(bodyBytes, encoding); | |
| 84 | |
| 85 set body(String value) { | |
| 86 bodyBytes = encodeString(value, encoding); | |
| 87 var contentType = _contentType; | |
| 88 if (contentType == null) contentType = new ContentType("text", "plain"); | |
| 89 if (contentType.charset == null) contentType.charset = encoding.name; | |
| 90 _contentType = contentType; | |
| 91 } | |
| 92 | |
| 93 /// The form-encoded fields in the body of the request as a map from field | |
| 94 /// names to values. The form-encoded body is converted to and from | |
| 95 /// [bodyBytes] using [encoding] (in the same way as [body]). | |
| 96 /// | |
| 97 /// If the request doesn't have a `Content-Type` header of | |
| 98 /// `application/x-www-form-urlencoded`, reading this will throw an | |
| 99 /// [UnsupportedError]. | |
| 100 /// | |
| 101 /// If the request has a `Content-Type` header with a type other than | |
| 102 /// `application/x-www-form-urlencoded`, setting this will throw an | |
| 103 /// [UnsupportedError]. Otherwise, the content type will be set to | |
| 104 /// `application/x-www-form-urlencoded`. | |
| 105 /// | |
| 106 /// This map should only be set, not modified in place. | |
| 107 Map<String, String> get bodyFields { | |
| 108 if (_contentType == null || | |
| 109 _contentType.value != "application/x-www-form-urlencoded") { | |
| 110 throw new UnsupportedError('Cannot access the body fields of a Request ' | |
|
Bob Nystrom
2012/10/31 01:17:44
Should be StateError I think.
nweiz
2012/10/31 18:20:59
Done.
| |
| 111 'without content-type "application/x-www-form-urlencoded".'); | |
| 112 } | |
| 113 | |
| 114 return queryToMap(body); | |
| 115 } | |
| 116 | |
| 117 set bodyFields(Map<String, String> fields) { | |
| 118 if (_contentType == null) { | |
| 119 _contentType = new ContentType("application", "x-www-form-urlencoded"); | |
| 120 } else if (_contentType.value != "application/x-www-form-urlencoded") { | |
| 121 throw new UnsupportedError('Cannot set the body fields of a Request with ' | |
| 122 'content-type "${_contentType.value}".'); | |
| 123 } | |
| 124 | |
| 125 this.body = mapToQuery(fields); | |
| 126 } | |
| 127 | |
| 128 /// Create a new HTTP request. | |
| 129 Request(String method, Uri url) | |
| 130 : super(method, url), | |
| 131 _defaultEncoding = Encoding.UTF_8, | |
| 132 _bodyBytes = new Uint8List(0); | |
| 133 | |
| 134 /// Freeze all mutable fields and return an [InputStream] containing the | |
| 135 /// request body. | |
| 136 InputStream finalize() { | |
| 137 super.finalize(); | |
| 138 | |
| 139 var stream = new ListInputStream(); | |
| 140 stream.write(bodyBytes); | |
| 141 stream.markEndOfStream(); | |
| 142 return stream; | |
| 143 } | |
| 144 | |
| 145 /// The `Content-Type` header of the request (if it exists) as a | |
| 146 /// [ContentType]. | |
| 147 ContentType get _contentType { | |
| 148 var contentType = headers[HttpHeaders.CONTENT_TYPE]; | |
| 149 if (contentType == null) return null; | |
| 150 return new ContentType.fromString(contentType); | |
| 151 } | |
| 152 | |
| 153 set _contentType(ContentType value) { | |
| 154 headers[HttpHeaders.CONTENT_TYPE] = value.toString(); | |
| 155 } | |
| 156 | |
| 157 /// Throw an error if this request has been finalized. | |
| 158 void _checkFinalized() { | |
| 159 if (!finalized) return; | |
| 160 throw new StateError("Can't modify a finalized Request."); | |
| 161 } | |
| 162 } | |
| OLD | NEW |