Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(358)

Side by Side Diff: dart/pkg/http_base/lib/http_base.dart

Issue 495533003: Remove obsolete http_base package (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « dart/pkg/http_base/README.md ('k') | dart/pkg/http_base/lib/http_base_html.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2014, 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 http_base;
6
7 import 'dart:async';
8
9 /// These headers should be ignored by [Client]s when making requests and when
10 /// receiving headers from a HTTP server.
11 const List<String> _TRANSPORT_HEADERS =
12 const ['connection', 'upgrade', 'keep-alive', 'transfer-encoding'];
13
14 /// These headers cannot be folded into one header value via ',' joining.
15 const List<String> _COOKIE_HEADERS = const ['set-cookie', 'cookie'];
16
17 /// Representation of a set of HTTP headers.
18 abstract class Headers {
19 /// Returns the names of all header fields.
20 Iterable<String> get names;
21
22 /// Returns `true` if a header field of the specified [name] exist.
23 bool contains(String name);
24
25 /// Returns the value for the header field named [name].
26 ///
27 /// The HTTP standard supports multiple values for each header field name.
28 /// Header fields with multiple values can be represented as a
29 /// comma-separated list. If a header has multiple values the returned string
30 /// is the comma-separated list of all these values.
31 ///
32 /// For header field-names which do not allow combining multiple values with
33 /// comma, this index operator will throw `ArgumentError`.
34 /// This is currently the case for the 'Cookie' and 'Set-Cookie' headers. Use
35 /// `getMultiple` method to iterate over the header values for these.
36 String operator [](String name);
37
38 /// Returns the values for the header field named [name].
39 ///
40 /// The order in which the values for the field name appear is the same
41 /// as the order in which they are to be send or was received.
42 ///
43 /// If there are no header values named [name] `null` will be returned.
44 Iterable<String> getMultiple(String name);
45 }
46
47
48 /// Representation of a HTTP request.
49 abstract class Request {
50 /// Request method.
51 String get method;
52
53 /// Request url.
54 Uri get url;
55
56 /// Request headers.
57 Headers get headers;
58
59 /// Request body.
60 Stream<List<int>> read();
61 }
62
63
64 /// Representation of a HTTP response.
65 abstract class Response {
66 /// Response status code.
67 int get statusCode;
68
69 /// Response headers.
70 Headers get headers;
71
72 /// Response body.
73 Stream<List<int>> read();
74 }
75
76
77 /// Function for performing an HTTP request.
78 ///
79 /// The [RequestHandler] may use any transport mechanism it wants
80 /// (e.g. HTTP/1.1, HTTP/2.0, SPDY) to perform the HTTP request.
81 ///
82 /// [RequestHandler]s are composable. E.g. A [RequestHandler] may add an
83 /// 'Authorization' header to [request] and forward to another [RequestHandler].
84 ///
85 /// A [RequestHandler] may ignore connection specific headers in [request] and
86 /// may not present them in the [Response] object.
87 ///
88 /// Connection specific headers:
89 /// 'Connection', 'Upgrade', 'Keep-Alive', 'Transfer-Encoding'
90 typedef Future<Response> RequestHandler(Request request);
91
92
93 /// An implementation of [Headers].
94 class HeadersImpl implements Headers {
95 static const HeadersImpl Empty = const HeadersImpl.empty();
96
97 final Map<String, List<String>> _m;
98
99 /// Constructs a [HeadersImpl] with no headers.
100 const HeadersImpl.empty() : _m = const {};
101
102 /// Constructs a new [HeaderImpl] initialized with [map].
103 ///
104 /// [map] must contain only String keys and either String or
105 /// Iterable<String> values.
106 HeadersImpl(Map map) : _m = {} {
107 _addDiff(map);
108 }
109
110 /// Makes a copy of this [HeadersImpl] and replaces all headers in present in
111 /// [differenceMap].
112 ///
113 /// [differenceMap] must contain only String keys and either String or
114 /// Iterable<String> values.
115 HeadersImpl replace(Map differenceMap) {
116 var headers = new HeadersImpl({});
117 _m.forEach((String key, List<String> value) {
118 headers._m[key] = value;
119 });
120 headers._addDiff(differenceMap);
121 return headers;
122 }
123
124 void _addDiff(Map diff) {
125 diff.forEach((String key, value) {
126 key = key.toLowerCase();
127
128 if (value == null) {
129 _m.remove(key);
130 } else if (value is String) {
131 var values = new List(1);
132 values[0] = value;
133 _m[key] = values;
134 } else {
135 _m[key] = value.toList();
136 }
137 });
138 }
139
140 Iterable<String> get names => _m.keys;
141
142 bool contains(String name) => _m.containsKey(name.toLowerCase());
143
144 String operator [](String name) {
145 name = name.toLowerCase();
146
147 if (_COOKIE_HEADERS.contains(name)) {
148 throw new ArgumentError('Cannot use Headers[] with $name header.');
149 }
150
151 var values = _m[name];
152 if (values == null) return null;
153 if (values.length == 1) return values.first;
154 return values.join(',');
155 }
156
157 Iterable<String> getMultiple(String name) {
158 name = name.toLowerCase();
159 var values = _m[name];
160 if (values == null) return values;
161
162 if (_COOKIE_HEADERS.contains(name)) {
163 return values;
164 } else {
165 return values.expand((e) => e.split(',')).map((e) => e.trim());
166 }
167 }
168 }
169
170
171 /// Internal helper class to reduce code duplication between [RequestImpl]
172 /// and [ResponseImpl].
173 class _Message {
174 final Headers headers;
175 final Stream<List<int>> _body;
176 bool _bodyRead = false;
177
178 _Message(Headers headers_, body)
179 : headers = headers_ != null ? headers_ : HeadersImpl.Empty,
180 _body = body != null ? body : (new StreamController()..close()).stream;
181
182 /// Returns the [Stream] of bytes of this message.
183 ///
184 /// The body of a message can only be read once.
185 Stream<List<int>> read() {
186 if (_bodyRead) {
187 throw new StateError('The response stream has already been listened to.');
188 }
189 _bodyRead = true;
190 return _body;
191 }
192 }
193
194
195 /// An immutable implementation of [Request].
196 ///
197 /// The request can be modified with the copy-on-write `replace` method.
198 class RequestImpl extends _Message implements Request {
199 final String method;
200 final Uri url;
201
202 RequestImpl(this.method, this.url, {Headers headers, Stream<List<int>> body})
203 : super(headers, body);
204
205 /// Makes a copy of this [RequestImpl] by overriding `method`, `url`,
206 /// `headers` and `body` if they are not null.
207 ///
208 /// In case no [body] was supplied, the current `body` will be used and is
209 /// therefore no longer available to users. This is a transfer of the owner
210 /// of the body stream to the returned object.
211 RequestImpl replace(
212 {String method, Uri url, Headers headers, Stream<List<int>> body}) {
213 if (method == null) method = this.method;
214 if (url == null) url = this.url;
215 if (headers == null) headers = this.headers;
216 if (body == null) body = read();
217
218 return new RequestImpl(method, url, headers: headers, body: body);
219 }
220 }
221
222
223 /// An immutable implementation of [Response].
224 ///
225 /// The response can be modified with the copy-on-write `replace` method.
226 class ResponseImpl extends _Message implements Response {
227 final int statusCode;
228
229 ResponseImpl(this.statusCode, {Headers headers, Stream<List<int>> body})
230 : super(headers, body);
231
232 /// Returns a copy of this [ResponseImpl] by overriding `statusCode`,
233 /// `headers` and `body` if they are not null.
234 ///
235 /// In case no [body] was supplied, the current `body` will be used and is
236 /// therefore no longer available to users. This is a transfer of the owner
237 /// of the body stream to the returned object.
238 ResponseImpl replace(
239 {int statusCode, Headers headers, Stream<List<int>> body}) {
240 if (statusCode == null) statusCode = this.statusCode;
241 if (headers == null) headers = this.headers;
242 if (body == null) body = read();
243
244 return new ResponseImpl(statusCode, headers: headers, body: body);
245 }
246 }
OLDNEW
« no previous file with comments | « dart/pkg/http_base/README.md ('k') | dart/pkg/http_base/lib/http_base_html.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698