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

Side by Side Diff: sdk/lib/io/http_impl.dart

Issue 124753002: Code cleanup (mostly io lib and some http lib). (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: integrate code review feedback Created 6 years, 11 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
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of dart.io; 5 part of dart.io;
6 6
7 const int _HEADERS_BUFFER_SIZE = 8 * 1024; 7 const int _HEADERS_BUFFER_SIZE = 8 * 1024;
8 8
9 class _HttpIncoming extends Stream<List<int>> { 9 class _HttpIncoming extends Stream<List<int>> {
10 final int _transferLength; 10 final int _transferLength;
(...skipping 15 matching lines...) Expand all
26 Uri uri; 26 Uri uri;
27 27
28 bool hasSubscriber = false; 28 bool hasSubscriber = false;
29 29
30 // The transfer length if the length of the message body as it 30 // The transfer length if the length of the message body as it
31 // appears in the message (RFC 2616 section 4.4). This can be -1 if 31 // appears in the message (RFC 2616 section 4.4). This can be -1 if
32 // the length of the massage body is not known due to transfer 32 // the length of the massage body is not known due to transfer
33 // codings. 33 // codings.
34 int get transferLength => _transferLength; 34 int get transferLength => _transferLength;
35 35
36 _HttpIncoming(_HttpHeaders this.headers, 36 _HttpIncoming(this.headers, this._transferLength, this._stream);
37 int this._transferLength,
38 Stream<List<int>> this._stream) {
39 }
40 37
41 StreamSubscription<List<int>> listen(void onData(List<int> event), 38 StreamSubscription<List<int>> listen(void onData(List<int> event),
42 {Function onError, 39 {Function onError,
43 void onDone(), 40 void onDone(),
44 bool cancelOnError}) { 41 bool cancelOnError}) {
45 hasSubscriber = true; 42 hasSubscriber = true;
46 return _stream 43 return _stream
47 .handleError((error) { 44 .handleError((error) {
48 throw new HttpException(error.message, uri: uri); 45 throw new HttpException(error.message, uri: uri);
49 }) 46 })
(...skipping 10 matching lines...) Expand all
60 fullBodyRead = true; 57 fullBodyRead = true;
61 hasSubscriber = true; 58 hasSubscriber = true;
62 _dataCompleter.complete(closing); 59 _dataCompleter.complete(closing);
63 } 60 }
64 } 61 }
65 62
66 abstract class _HttpInboundMessage extends Stream<List<int>> { 63 abstract class _HttpInboundMessage extends Stream<List<int>> {
67 final _HttpIncoming _incoming; 64 final _HttpIncoming _incoming;
68 List<Cookie> _cookies; 65 List<Cookie> _cookies;
69 66
70 _HttpInboundMessage(_HttpIncoming this._incoming); 67 _HttpInboundMessage(this._incoming);
71 68
72 List<Cookie> get cookies { 69 List<Cookie> get cookies {
73 if (_cookies != null) return _cookies; 70 if (_cookies != null) return _cookies;
74 return _cookies = headers._parseCookies(); 71 return _cookies = headers._parseCookies();
75 } 72 }
76 73
77 _HttpHeaders get headers => _incoming.headers; 74 _HttpHeaders get headers => _incoming.headers;
78 String get protocolVersion => headers.protocolVersion; 75 String get protocolVersion => headers.protocolVersion;
79 int get contentLength => headers.contentLength; 76 int get contentLength => headers.contentLength;
80 bool get persistentConnection => headers.persistentConnection; 77 bool get persistentConnection => headers.persistentConnection;
81 } 78 }
82 79
83 80
84 class _HttpRequest extends _HttpInboundMessage implements HttpRequest { 81 class _HttpRequest extends _HttpInboundMessage implements HttpRequest {
85 final HttpResponse response; 82 final HttpResponse response;
86 83
87 final _HttpServer _httpServer; 84 final _HttpServer _httpServer;
88 85
89 final _HttpConnection _httpConnection; 86 final _HttpConnection _httpConnection;
90 87
91 _HttpSession _session; 88 _HttpSession _session;
92 89
93 _HttpRequest(_HttpResponse this.response, 90 _HttpRequest(this.response, _HttpIncoming _incoming, this._httpServer,
94 _HttpIncoming _incoming, 91 this._httpConnection) : super(_incoming) {
95 _HttpServer this._httpServer,
96 _HttpConnection this._httpConnection)
97 : super(_incoming) {
98 if (headers.protocolVersion == "1.1") { 92 if (headers.protocolVersion == "1.1") {
99 response.headers.chunkedTransferEncoding = true; 93 response.headers
100 response.headers.persistentConnection = headers.persistentConnection; 94 ..chunkedTransferEncoding = true
95 ..persistentConnection = headers.persistentConnection;
101 } 96 }
102 97
103 if (_httpServer._sessionManagerInstance != null) { 98 if (_httpServer._sessionManagerInstance != null) {
104 // Map to session if exists. 99 // Map to session if exists.
105 var sessionIds = cookies 100 var sessionIds = cookies
106 .where((cookie) => cookie.name.toUpperCase() == _DART_SESSION_ID) 101 .where((cookie) => cookie.name.toUpperCase() == _DART_SESSION_ID)
107 .map((cookie) => cookie.value); 102 .map((cookie) => cookie.value);
108 for (var sessionId in sessionIds) { 103 for (var sessionId in sessionIds) {
109 _session = _httpServer._sessionManager.getSession(sessionId); 104 _session = _httpServer._sessionManager.getSession(sessionId);
110 if (_session != null) { 105 if (_session != null) {
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
159 List<RedirectInfo> get redirects => _httpRequest._responseRedirects; 154 List<RedirectInfo> get redirects => _httpRequest._responseRedirects;
160 155
161 // The HttpClient this response belongs to. 156 // The HttpClient this response belongs to.
162 final _HttpClient _httpClient; 157 final _HttpClient _httpClient;
163 158
164 // The HttpClientRequest of this response. 159 // The HttpClientRequest of this response.
165 final _HttpClientRequest _httpRequest; 160 final _HttpClientRequest _httpRequest;
166 161
167 List<Cookie> _cookies; 162 List<Cookie> _cookies;
168 163
169 _HttpClientResponse(_HttpIncoming _incoming, 164 _HttpClientResponse(_HttpIncoming _incoming, this._httpRequest,
170 _HttpClientRequest this._httpRequest, 165 this._httpClient) : super(_incoming) {
171 _HttpClient this._httpClient)
172 : super(_incoming) {
173 // Set uri for potential exceptions. 166 // Set uri for potential exceptions.
174 _incoming.uri = _httpRequest.uri; 167 _incoming.uri = _httpRequest.uri;
175 } 168 }
176 169
177 int get statusCode => _incoming.statusCode; 170 int get statusCode => _incoming.statusCode;
178 String get reasonPhrase => _incoming.reasonPhrase; 171 String get reasonPhrase => _incoming.reasonPhrase;
179 172
180 X509Certificate get certificate { 173 X509Certificate get certificate =>
181 var socket = _httpRequest._httpClientConnection._socket; 174 _httpRequest._httpClientConnection._socket.peerCertificate;
182 return socket.peerCertificate;
183 }
184 175
185 List<Cookie> get cookies { 176 List<Cookie> get cookies {
186 if (_cookies != null) return _cookies; 177 if (_cookies != null) return _cookies;
187 _cookies = new List<Cookie>(); 178 _cookies = new List<Cookie>();
188 List<String> values = headers[HttpHeaders.SET_COOKIE]; 179 List<String> values = headers[HttpHeaders.SET_COOKIE];
189 if (values != null) { 180 if (values != null) {
190 values.forEach((value) { 181 values.forEach((value) {
191 _cookies.add(new Cookie.fromSetCookieValue(value)); 182 _cookies.add(new Cookie.fromSetCookieValue(value));
192 }); 183 });
193 } 184 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
227 if (followLoops != true) { 218 if (followLoops != true) {
228 for (var redirect in redirects) { 219 for (var redirect in redirects) {
229 if (redirect.location == url) { 220 if (redirect.location == url) {
230 return new Future.error( 221 return new Future.error(
231 new RedirectException("Redirect loop detected", redirects)); 222 new RedirectException("Redirect loop detected", redirects));
232 } 223 }
233 } 224 }
234 } 225 }
235 return _httpClient._openUrlFromRequest(method, url, _httpRequest) 226 return _httpClient._openUrlFromRequest(method, url, _httpRequest)
236 .then((request) { 227 .then((request) {
237 request._responseRedirects.addAll(this.redirects); 228 request._responseRedirects
238 request._responseRedirects.add(new _RedirectInfo(statusCode, 229 ..addAll(this.redirects)
239 method, 230 ..add(new _RedirectInfo(statusCode, method, url));
240 url));
241 return request.close(); 231 return request.close();
242 }); 232 });
243 } 233 }
244 234
245 StreamSubscription<List<int>> listen(void onData(List<int> event), 235 StreamSubscription<List<int>> listen(void onData(List<int> event),
246 {Function onError, 236 {Function onError,
247 void onDone(), 237 void onDone(),
248 bool cancelOnError}) { 238 bool cancelOnError}) {
249 var stream = _incoming; 239 var stream = _incoming;
250 if (headers.value(HttpHeaders.CONTENT_ENCODING) == "gzip") { 240 if (headers.value(HttpHeaders.CONTENT_ENCODING) == "gzip") {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
282 // Drain body and retry. 272 // Drain body and retry.
283 return drain().then((_) { 273 return drain().then((_) {
284 return _httpClient._openUrlFromRequest(_httpRequest.method, 274 return _httpClient._openUrlFromRequest(_httpRequest.method,
285 _httpRequest.uri, 275 _httpRequest.uri,
286 _httpRequest) 276 _httpRequest)
287 .then((request) => request.close()); 277 .then((request) => request.close());
288 }); 278 });
289 } 279 }
290 280
291 List<String> authChallenge() { 281 List<String> authChallenge() {
292 if (proxyAuth) { 282 return proxyAuth ? headers[HttpHeaders.PROXY_AUTHENTICATE]
293 return headers[HttpHeaders.PROXY_AUTHENTICATE]; 283 : headers[HttpHeaders.WWW_AUTHENTICATE];
294 } else {
295 return headers[HttpHeaders.WWW_AUTHENTICATE];
296 }
297 } 284 }
298 285
299 _Credentials findCredentials(_AuthenticationScheme scheme) { 286 _Credentials findCredentials(_AuthenticationScheme scheme) {
300 if (proxyAuth) { 287 return proxyAuth ? _httpClient._findProxyCredentials(_httpRequest._proxy, scheme)
301 return _httpClient._findProxyCredentials(_httpRequest._proxy, scheme); 288 : _httpClient._findCredentials(_httpRequest.uri, scheme);
302 } else {
303 return _httpClient._findCredentials(_httpRequest.uri, scheme);
304 }
305 } 289 }
306 290
307 void removeCredentials(_Credentials cr) { 291 void removeCredentials(_Credentials cr) {
308 if (proxyAuth) { 292 if (proxyAuth) {
309 _httpClient._removeProxyCredentials(cr); 293 _httpClient._removeProxyCredentials(cr);
310 } else { 294 } else {
311 _httpClient._removeCredentials(cr); 295 _httpClient._removeCredentials(cr);
312 } 296 }
313 } 297 }
314 298
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
352 } 336 }
353 337
354 // Digest authentication only supports the MD5 algorithm. 338 // Digest authentication only supports the MD5 algorithm.
355 if (cr.scheme == _AuthenticationScheme.DIGEST && 339 if (cr.scheme == _AuthenticationScheme.DIGEST &&
356 (header.parameters["algorithm"] == null || 340 (header.parameters["algorithm"] == null ||
357 header.parameters["algorithm"].toLowerCase() == "md5")) { 341 header.parameters["algorithm"].toLowerCase() == "md5")) {
358 if (cr.nonce == null || cr.nonce == header.parameters["nonce"]) { 342 if (cr.nonce == null || cr.nonce == header.parameters["nonce"]) {
359 // If the nonce is not set then this is the first authenticate 343 // If the nonce is not set then this is the first authenticate
360 // response for these credentials. Set up authentication state. 344 // response for these credentials. Set up authentication state.
361 if (cr.nonce == null) { 345 if (cr.nonce == null) {
362 cr.nonce = header.parameters["nonce"]; 346 cr..nonce = header.parameters["nonce"]
363 cr.algorithm = "MD5"; 347 ..algorithm = "MD5"
364 cr.qop = header.parameters["qop"]; 348 ..qop = header.parameters["qop"]
365 cr.nonceCount = 0; 349 ..nonceCount = 0;
366 } 350 }
367 // Credentials where found, prepare for retrying the request. 351 // Credentials where found, prepare for retrying the request.
368 return retry(); 352 return retry();
369 } else if (header.parameters["stale"] != null && 353 } else if (header.parameters["stale"] != null &&
370 header.parameters["stale"].toLowerCase() == "true") { 354 header.parameters["stale"].toLowerCase() == "true") {
371 // If stale is true retry with new nonce. 355 // If stale is true retry with new nonce.
372 cr.nonce = header.parameters["nonce"]; 356 cr.nonce = header.parameters["nonce"];
373 // Credentials where found, prepare for retrying the request. 357 // Credentials where found, prepare for retrying the request.
374 return retry(); 358 return retry();
375 } 359 }
(...skipping 28 matching lines...) Expand all
404 bool _asGZip = false; 388 bool _asGZip = false;
405 389
406 IOSink _headersSink; 390 IOSink _headersSink;
407 IOSink _dataSink; 391 IOSink _dataSink;
408 392
409 final _HttpOutgoing _outgoing; 393 final _HttpOutgoing _outgoing;
410 final Uri _uri; 394 final Uri _uri;
411 395
412 final _HttpHeaders headers; 396 final _HttpHeaders headers;
413 397
414 _HttpOutboundMessage(Uri this._uri, 398 _HttpOutboundMessage(this._uri,
415 String protocolVersion, 399 String protocolVersion,
416 _HttpOutgoing outgoing) 400 _HttpOutgoing outgoing)
417 : _outgoing = outgoing, 401 : _outgoing = outgoing,
418 _headersSink = new IOSink(outgoing, encoding: ASCII), 402 _headersSink = new IOSink(outgoing, encoding: ASCII),
419 headers = new _HttpHeaders(protocolVersion) { 403 headers = new _HttpHeaders(protocolVersion) {
420 _dataSink = new IOSink(new _HttpOutboundConsumer(this)); 404 _dataSink = new IOSink(new _HttpOutboundConsumer(this));
421 } 405 }
422 406
423 int get contentLength => headers.contentLength; 407 int get contentLength => headers.contentLength;
424 void set contentLength(int contentLength) { 408 void set contentLength(int contentLength) {
(...skipping 12 matching lines...) Expand all
437 } else { 421 } else {
438 charset = "iso-8859-1"; 422 charset = "iso-8859-1";
439 } 423 }
440 return Encoding.getByName(charset); 424 return Encoding.getByName(charset);
441 } 425 }
442 426
443 void set encoding(Encoding value) { 427 void set encoding(Encoding value) {
444 throw new StateError("IOSink encoding is not mutable"); 428 throw new StateError("IOSink encoding is not mutable");
445 } 429 }
446 430
447 void write(Object obj) { 431 void write(Object obj) => _dataSink.write(obj);
448 _dataSink.write(obj);
449 }
450 432
451 void writeAll(Iterable objects, [String separator = ""]) { 433 void writeAll(Iterable objects, [String separator = ""]) =>
452 _dataSink.writeAll(objects, separator); 434 _dataSink.writeAll(objects, separator);
453 }
454 435
455 void writeln([Object obj = ""]) { 436 void writeln([Object obj = ""]) => _dataSink.writeln(obj);
456 _dataSink.writeln(obj);
457 }
458 437
459 void writeCharCode(int charCode) { 438 void writeCharCode(int charCode) => _dataSink.writeCharCode(charCode);
460 _dataSink.writeCharCode(charCode);
461 }
462 439
463 void add(List<int> data) { 440 void add(List<int> data) {
464 if (data.length == 0) return; 441 if (data.length == 0) return;
465 _dataSink.add(data); 442 _dataSink.add(data);
466 } 443 }
467 444
468 void addError(error, [StackTrace stackTrace]) { 445 void addError(error, [StackTrace stackTrace]) =>
469 _dataSink.addError(error, stackTrace); 446 _dataSink.addError(error, stackTrace);
470 }
471 447
472 Future<T> addStream(Stream<List<int>> stream) { 448 Future<T> addStream(Stream<List<int>> stream) => _dataSink.addStream(stream);
473 return _dataSink.addStream(stream);
474 }
475 449
476 Future flush() { 450 Future flush() => _dataSink.flush();
477 return _dataSink.flush();
478 }
479 451
480 Future close() { 452 Future close() => _dataSink.close();
481 return _dataSink.close();
482 }
483 453
484 Future<T> get done => _dataSink.done; 454 Future<T> get done => _dataSink.done;
485 455
486 Future _writeHeaders({bool drainRequest: true}) { 456 Future _writeHeaders({bool drainRequest: true}) {
487 void write() { 457 void write() {
488 try { 458 try {
489 _writeHeader(); 459 _writeHeader();
490 } catch (error) { 460 } catch (error) {
491 // Headers too large. 461 // Headers too large.
492 throw new HttpException( 462 throw new HttpException(
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
568 538
569 539
570 class _HttpOutboundConsumer implements StreamConsumer { 540 class _HttpOutboundConsumer implements StreamConsumer {
571 final _HttpOutboundMessage _outbound; 541 final _HttpOutboundMessage _outbound;
572 StreamController _controller; 542 StreamController _controller;
573 StreamSubscription _subscription; 543 StreamSubscription _subscription;
574 Completer _closeCompleter = new Completer(); 544 Completer _closeCompleter = new Completer();
575 Completer _completer; 545 Completer _completer;
576 bool _socketError = false; 546 bool _socketError = false;
577 547
578 _HttpOutboundConsumer(_HttpOutboundMessage this._outbound); 548 _HttpOutboundConsumer(this._outbound);
579 549
580 void _cancel() { 550 void _cancel() {
581 if (_subscription != null) { 551 if (_subscription != null) {
582 StreamSubscription subscription = _subscription; 552 StreamSubscription subscription = _subscription;
583 _subscription = null; 553 _subscription = null;
584 subscription.cancel(); 554 subscription.cancel();
585 } 555 }
586 } 556 }
587 557
588 bool _ignoreError(error) 558 bool _ignoreError(error)
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
806 buffer[offset++] = _CharCode.LF; 776 buffer[offset++] = _CharCode.LF;
807 777
808 var session = _httpRequest._session; 778 var session = _httpRequest._session;
809 if (session != null && !session._destroyed) { 779 if (session != null && !session._destroyed) {
810 // Mark as not new. 780 // Mark as not new.
811 session._isNew = false; 781 session._isNew = false;
812 // Make sure we only send the current session id. 782 // Make sure we only send the current session id.
813 bool found = false; 783 bool found = false;
814 for (int i = 0; i < cookies.length; i++) { 784 for (int i = 0; i < cookies.length; i++) {
815 if (cookies[i].name.toUpperCase() == _DART_SESSION_ID) { 785 if (cookies[i].name.toUpperCase() == _DART_SESSION_ID) {
816 cookies[i].value = session.id; 786 cookies[i]
817 cookies[i].httpOnly = true; 787 ..value = session.id
818 cookies[i].path = "/"; 788 ..httpOnly = true
789 ..path = "/";
819 found = true; 790 found = true;
820 } 791 }
821 } 792 }
822 if (!found) { 793 if (!found) {
823 var cookie = new Cookie(_DART_SESSION_ID, session.id); 794 var cookie = new Cookie(_DART_SESSION_ID, session.id);
824 cookie.httpOnly = true; 795 cookies.add(cookie
825 cookie.path = "/"; 796 ..httpOnly = true
826 cookies.add(cookie); 797 ..path = "/");
827 } 798 }
828 } 799 }
829 // Add all the cookies set to the headers. 800 // Add all the cookies set to the headers.
830 if (_cookies != null) { 801 if (_cookies != null) {
831 _cookies.forEach((cookie) { 802 _cookies.forEach((cookie) {
832 headers.add(HttpHeaders.SET_COOKIE, cookie); 803 headers.add(HttpHeaders.SET_COOKIE, cookie);
833 }); 804 });
834 } 805 }
835 806
836 headers._finalize(); 807 headers._finalize();
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
916 887
917 Future<HttpClientResponse> _response; 888 Future<HttpClientResponse> _response;
918 889
919 // TODO(ajohnsen): Get default value from client? 890 // TODO(ajohnsen): Get default value from client?
920 bool _followRedirects = true; 891 bool _followRedirects = true;
921 892
922 int _maxRedirects = 5; 893 int _maxRedirects = 5;
923 894
924 List<RedirectInfo> _responseRedirects = []; 895 List<RedirectInfo> _responseRedirects = [];
925 896
926 _HttpClientRequest(_HttpOutgoing outgoing, 897 _HttpClientRequest(_HttpOutgoing outgoing, Uri uri, this.method, this._proxy,
927 Uri uri, 898 this._httpClient, this._httpClientConnection)
928 String this.method,
929 _Proxy this._proxy,
930 _HttpClient this._httpClient,
931 _HttpClientConnection this._httpClientConnection)
932 : super(uri, "1.1", outgoing), 899 : super(uri, "1.1", outgoing),
933 uri = uri { 900 uri = uri {
934 // GET and HEAD have 'content-length: 0' by default. 901 // GET and HEAD have 'content-length: 0' by default.
935 if (method == "GET" || method == "HEAD") { 902 if (method == "GET" || method == "HEAD") {
936 contentLength = 0; 903 contentLength = 0;
937 } else { 904 } else {
938 headers.chunkedTransferEncoding = true; 905 headers.chunkedTransferEncoding = true;
939 } 906 }
940 } 907 }
941 908
(...skipping 19 matching lines...) Expand all
961 928
962 bool get followRedirects => _followRedirects; 929 bool get followRedirects => _followRedirects;
963 void set followRedirects(bool followRedirects) { 930 void set followRedirects(bool followRedirects) {
964 if (_headersWritten) throw new StateError("Request already sent"); 931 if (_headersWritten) throw new StateError("Request already sent");
965 _followRedirects = followRedirects; 932 _followRedirects = followRedirects;
966 } 933 }
967 934
968 HttpConnectionInfo get connectionInfo => _httpClientConnection.connectionInfo; 935 HttpConnectionInfo get connectionInfo => _httpClientConnection.connectionInfo;
969 936
970 void _onIncoming(_HttpIncoming incoming) { 937 void _onIncoming(_HttpIncoming incoming) {
971 var response = new _HttpClientResponse(incoming, 938 var response = new _HttpClientResponse(incoming, this, _httpClient);
972 this,
973 _httpClient);
974 Future<HttpClientResponse> future; 939 Future<HttpClientResponse> future;
975 if (followRedirects && response.isRedirect) { 940 if (followRedirects && response.isRedirect) {
976 if (response.redirects.length < maxRedirects) { 941 if (response.redirects.length < maxRedirects) {
977 // Redirect and drain response. 942 // Redirect and drain response.
978 future = response.drain() 943 future = response.drain().then((_) => response.redirect());
979 .then((_) => response.redirect());
980 } else { 944 } else {
981 // End with exception, too many redirects. 945 // End with exception, too many redirects.
982 future = response.drain() 946 future = response.drain()
983 .then((_) => new Future.error( 947 .then((_) => new Future.error(
984 new RedirectException("Redirect limit exceeded", 948 new RedirectException("Redirect limit exceeded",
985 response.redirects))); 949 response.redirects)));
986 } 950 }
987 } else if (response._shouldAuthenticateProxy) { 951 } else if (response._shouldAuthenticateProxy) {
988 future = response._authenticate(true); 952 future = response._authenticate(true);
989 } else if (response._shouldAuthenticate) { 953 } else if (response._shouldAuthenticate) {
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
1055 // Write HTTP/1.1. 1019 // Write HTTP/1.1.
1056 write(_Const.HTTP11); 1020 write(_Const.HTTP11);
1057 buffer[offset++] = _CharCode.CR; 1021 buffer[offset++] = _CharCode.CR;
1058 buffer[offset++] = _CharCode.LF; 1022 buffer[offset++] = _CharCode.LF;
1059 1023
1060 // Add the cookies to the headers. 1024 // Add the cookies to the headers.
1061 if (!cookies.isEmpty) { 1025 if (!cookies.isEmpty) {
1062 StringBuffer sb = new StringBuffer(); 1026 StringBuffer sb = new StringBuffer();
1063 for (int i = 0; i < cookies.length; i++) { 1027 for (int i = 0; i < cookies.length; i++) {
1064 if (i > 0) sb.write("; "); 1028 if (i > 0) sb.write("; ");
1065 sb.write(cookies[i].name); 1029 sb..write(cookies[i].name)
1066 sb.write("="); 1030 ..write("=")
1067 sb.write(cookies[i].value); 1031 ..write(cookies[i].value);
1068 } 1032 }
1069 headers.add(HttpHeaders.COOKIE, sb.toString()); 1033 headers.add(HttpHeaders.COOKIE, sb.toString());
1070 } 1034 }
1071 1035
1072 headers._finalize(); 1036 headers._finalize();
1073 1037
1074 // Write headers. 1038 // Write headers.
1075 offset = headers._write(buffer, offset); 1039 offset = headers._write(buffer, offset);
1076 buffer[offset++] = _CharCode.CR; 1040 buffer[offset++] = _CharCode.CR;
1077 buffer[offset++] = _CharCode.LF; 1041 buffer[offset++] = _CharCode.LF;
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
1152 1116
1153 // Transformer that validates the content length. 1117 // Transformer that validates the content length.
1154 class _ContentLengthValidator 1118 class _ContentLengthValidator
1155 implements StreamTransformer<List<int>, List<int>>, EventSink<List<int>> { 1119 implements StreamTransformer<List<int>, List<int>>, EventSink<List<int>> {
1156 final int expectedContentLength; 1120 final int expectedContentLength;
1157 final Uri uri; 1121 final Uri uri;
1158 int _bytesWritten = 0; 1122 int _bytesWritten = 0;
1159 1123
1160 EventSink<List<int>> _outSink; 1124 EventSink<List<int>> _outSink;
1161 1125
1162 _ContentLengthValidator(int this.expectedContentLength, Uri this.uri); 1126 _ContentLengthValidator(this.expectedContentLength, this.uri);
1163 1127
1164 Stream<List<int>> bind(Stream<List<int>> stream) { 1128 Stream<List<int>> bind(Stream<List<int>> stream) {
1165 return new Stream.eventTransformed( 1129 return new Stream.eventTransformed(
1166 stream, 1130 stream,
1167 (EventSink sink) { 1131 (EventSink sink) {
1168 if (_outSink != null) { 1132 if (_outSink != null) {
1169 throw new StateError("Validator transformer already used"); 1133 throw new StateError("Validator transformer already used");
1170 } 1134 }
1171 _outSink = sink; 1135 _outSink = sink;
1172 return this; 1136 return this;
(...skipping 30 matching lines...) Expand all
1203 _outSink.close(); 1167 _outSink.close();
1204 } 1168 }
1205 } 1169 }
1206 1170
1207 1171
1208 // Extends StreamConsumer as this is an internal type, only used to pipe to. 1172 // Extends StreamConsumer as this is an internal type, only used to pipe to.
1209 class _HttpOutgoing implements StreamConsumer<List<int>> { 1173 class _HttpOutgoing implements StreamConsumer<List<int>> {
1210 final Completer _doneCompleter = new Completer(); 1174 final Completer _doneCompleter = new Completer();
1211 final Socket socket; 1175 final Socket socket;
1212 1176
1213 _HttpOutgoing(Socket this.socket); 1177 _HttpOutgoing(this.socket);
1214 1178
1215 Future addStream(Stream<List<int>> stream) { 1179 Future addStream(Stream<List<int>> stream) {
1216 return socket.addStream(stream) 1180 return socket.addStream(stream)
1217 .catchError((error) { 1181 .catchError((error) {
1218 _doneCompleter.completeError(error); 1182 _doneCompleter.completeError(error);
1219 throw error; 1183 throw error;
1220 }); 1184 });
1221 } 1185 }
1222 1186
1223 Future close() { 1187 Future close() {
(...skipping 13 matching lines...) Expand all
1237 final _HttpClient _httpClient; 1201 final _HttpClient _httpClient;
1238 bool _dispose = false; 1202 bool _dispose = false;
1239 Timer _idleTimer; 1203 Timer _idleTimer;
1240 bool closed = false; 1204 bool closed = false;
1241 Uri _currentUri; 1205 Uri _currentUri;
1242 final Uint8List _headersBuffer = new Uint8List(_HEADERS_BUFFER_SIZE); 1206 final Uint8List _headersBuffer = new Uint8List(_HEADERS_BUFFER_SIZE);
1243 1207
1244 Completer<_HttpIncoming> _nextResponseCompleter; 1208 Completer<_HttpIncoming> _nextResponseCompleter;
1245 Future _streamFuture; 1209 Future _streamFuture;
1246 1210
1247 _HttpClientConnection(String this.key, 1211 _HttpClientConnection(this.key, this._socket, this._httpClient,
1248 Socket this._socket,
1249 _HttpClient this._httpClient,
1250 [this._proxyTunnel = false]) 1212 [this._proxyTunnel = false])
1251 : _httpParser = new _HttpParser.responseParser() { 1213 : _httpParser = new _HttpParser.responseParser() {
1252 _socket.pipe(_httpParser); 1214 _socket.pipe(_httpParser);
1253 1215
1254 // Set up handlers on the parser here, so we are sure to get 'onDone' from 1216 // Set up handlers on the parser here, so we are sure to get 'onDone' from
1255 // the parser. 1217 // the parser.
1256 _subscription = _httpParser.listen( 1218 _subscription = _httpParser.listen(
1257 (incoming) { 1219 (incoming) {
1258 // Only handle one incoming response at the time. Keep the 1220 // Only handle one incoming response at the time. Keep the
1259 // stream paused until the response have been processed. 1221 // stream paused until the response have been processed.
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1295 _ProxyCredentials proxyCreds; // Credentials used to authorize proxy. 1257 _ProxyCredentials proxyCreds; // Credentials used to authorize proxy.
1296 _SiteCredentials creds; // Credentials used to authorize this request. 1258 _SiteCredentials creds; // Credentials used to authorize this request.
1297 var outgoing = new _HttpOutgoing(_socket); 1259 var outgoing = new _HttpOutgoing(_socket);
1298 // Create new request object, wrapping the outgoing connection. 1260 // Create new request object, wrapping the outgoing connection.
1299 var request = new _HttpClientRequest(outgoing, 1261 var request = new _HttpClientRequest(outgoing,
1300 uri, 1262 uri,
1301 method, 1263 method,
1302 proxy, 1264 proxy,
1303 _httpClient, 1265 _httpClient,
1304 this); 1266 this);
1305 request.headers.host = uri.host; 1267 request.headers
1306 request.headers.port = port; 1268 ..host = uri.host
1307 request.headers._add(HttpHeaders.ACCEPT_ENCODING, "gzip"); 1269 ..port = port
1270 .._add(HttpHeaders.ACCEPT_ENCODING, "gzip");
1308 if (_httpClient.userAgent != null) { 1271 if (_httpClient.userAgent != null) {
1309 request.headers._add('user-agent', _httpClient.userAgent); 1272 request.headers._add('user-agent', _httpClient.userAgent);
1310 } 1273 }
1311 if (proxy.isAuthenticated) { 1274 if (proxy.isAuthenticated) {
1312 // If the proxy configuration contains user information use that 1275 // If the proxy configuration contains user information use that
1313 // for proxy basic authorization. 1276 // for proxy basic authorization.
1314 String auth = _CryptoUtils.bytesToBase64( 1277 String auth = _CryptoUtils.bytesToBase64(
1315 UTF8.encode("${proxy.username}:${proxy.password}")); 1278 UTF8.encode("${proxy.username}:${proxy.password}"));
1316 request.headers.set(HttpHeaders.PROXY_AUTHORIZATION, "Basic $auth"); 1279 request.headers.set(HttpHeaders.PROXY_AUTHORIZATION, "Basic $auth");
1317 } else if (!proxy.isDirect && _httpClient._proxyCredentials.length > 0) { 1280 } else if (!proxy.isDirect && _httpClient._proxyCredentials.length > 0) {
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
1473 _idleTimer = new Timer( 1436 _idleTimer = new Timer(
1474 _httpClient.idleTimeout, 1437 _httpClient.idleTimeout,
1475 () { 1438 () {
1476 _idleTimer = null; 1439 _idleTimer = null;
1477 close(); 1440 close();
1478 }); 1441 });
1479 } 1442 }
1480 } 1443 }
1481 1444
1482 class _ConnnectionInfo { 1445 class _ConnnectionInfo {
1483 _ConnnectionInfo(_HttpClientConnection this.connection, _Proxy this.proxy);
1484 final _HttpClientConnection connection; 1446 final _HttpClientConnection connection;
1485 final _Proxy proxy; 1447 final _Proxy proxy;
1448
1449 _ConnnectionInfo(this.connection, this.proxy);
1486 } 1450 }
1487 1451
1488 1452
1489 class _HttpClient implements HttpClient { 1453 class _HttpClient implements HttpClient {
1490 // TODO(ajohnsen): Use eviction timeout. 1454 // TODO(ajohnsen): Use eviction timeout.
1491 bool _closing = false; 1455 bool _closing = false;
1492 1456
1493 final Map<String, Set<_HttpClientConnection>> _idleConnections 1457 final Map<String, Set<_HttpClientConnection>> _idleConnections
1494 = new HashMap<String, Set<_HttpClientConnection>>(); 1458 = new HashMap<String, Set<_HttpClientConnection>>();
1495 final Set<_HttpClientConnection> _activeConnections 1459 final Set<_HttpClientConnection> _activeConnections
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
1579 } 1543 }
1580 assert(_activeConnections.isEmpty); 1544 assert(_activeConnections.isEmpty);
1581 _activeConnections.clear(); 1545 _activeConnections.clear();
1582 } 1546 }
1583 } 1547 }
1584 1548
1585 set authenticate(Future<bool> f(Uri url, String scheme, String realm)) { 1549 set authenticate(Future<bool> f(Uri url, String scheme, String realm)) {
1586 _authenticate = f; 1550 _authenticate = f;
1587 } 1551 }
1588 1552
1589 void addCredentials(Uri url, String realm, HttpClientCredentials cr) { 1553 void addCredentials(Uri url, String realm, HttpClientCredentials cr) =>
1590 _credentials.add(new _SiteCredentials(url, realm, cr)); 1554 _credentials.add(new _SiteCredentials(url, realm, cr));
1591 }
1592 1555
1593 set authenticateProxy( 1556 set authenticateProxy(
1594 Future<bool> f(String host, int port, String scheme, String realm)) { 1557 Future<bool> f(String host, int port, String scheme, String realm)) {
1595 _authenticateProxy = f; 1558 _authenticateProxy = f;
1596 } 1559 }
1597 1560
1598 void addProxyCredentials(String host, 1561 void addProxyCredentials(String host,
1599 int port, 1562 int port,
1600 String realm, 1563 String realm,
1601 HttpClientCredentials cr) { 1564 HttpClientCredentials cr) =>
1602 _proxyCredentials.add(new _ProxyCredentials(host, port, realm, cr)); 1565 _proxyCredentials.add(new _ProxyCredentials(host, port, realm, cr));
1603 }
1604 1566
1605 set findProxy(String f(Uri uri)) => _findProxy = f; 1567 set findProxy(String f(Uri uri)) => _findProxy = f;
1606 1568
1607 Future<HttpClientRequest> _openUrl(String method, Uri uri) { 1569 Future<HttpClientRequest> _openUrl(String method, Uri uri) {
1608 if (method == null) { 1570 if (method == null) {
1609 throw new ArgumentError(method); 1571 throw new ArgumentError(method);
1610 } 1572 }
1611 if (method != "CONNECT") { 1573 if (method != "CONNECT") {
1612 if (uri.host.isEmpty) { 1574 if (uri.host.isEmpty) {
1613 throw new ArgumentError("No host specified in URI $uri"); 1575 throw new ArgumentError("No host specified in URI $uri");
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1653 }); 1615 });
1654 } 1616 }
1655 1617
1656 Future<HttpClientRequest> _openUrlFromRequest(String method, 1618 Future<HttpClientRequest> _openUrlFromRequest(String method,
1657 Uri uri, 1619 Uri uri,
1658 _HttpClientRequest previous) { 1620 _HttpClientRequest previous) {
1659 // If the new URI is relative (to either '/' or some sub-path), 1621 // If the new URI is relative (to either '/' or some sub-path),
1660 // construct a full URI from the previous one. 1622 // construct a full URI from the previous one.
1661 Uri resolved = previous.uri.resolveUri(uri); 1623 Uri resolved = previous.uri.resolveUri(uri);
1662 return openUrl(method, resolved).then((_HttpClientRequest request) { 1624 return openUrl(method, resolved).then((_HttpClientRequest request) {
1663 // Only follow redirects if initial request did. 1625
1664 request.followRedirects = previous.followRedirects; 1626 request
1665 // Allow same number of redirects. 1627 // Only follow redirects if initial request did.
1666 request.maxRedirects = previous.maxRedirects; 1628 ..followRedirects = previous.followRedirects
1629 // Allow same number of redirects.
1630 ..maxRedirects = previous.maxRedirects;
1667 // Copy headers. 1631 // Copy headers.
1668 for (var header in previous.headers._headers.keys) { 1632 for (var header in previous.headers._headers.keys) {
1669 if (request.headers[header] == null) { 1633 if (request.headers[header] == null) {
1670 request.headers.set(header, previous.headers[header]); 1634 request.headers.set(header, previous.headers[header]);
1671 } 1635 }
1672 } 1636 }
1673 request.headers.chunkedTransferEncoding = false; 1637 return request
1674 request.contentLength = 0; 1638 ..headers.chunkedTransferEncoding = false
1675 return request; 1639 ..contentLength = 0;
1676 }); 1640 });
1677 } 1641 }
1678 1642
1679 // Return a live connection to the idle pool. 1643 // Return a live connection to the idle pool.
1680 void _returnConnection(_HttpClientConnection connection) { 1644 void _returnConnection(_HttpClientConnection connection) {
1681 _activeConnections.remove(connection); 1645 _activeConnections.remove(connection);
1682 if (_closing) { 1646 if (_closing) {
1683 connection.close(); 1647 connection.close();
1684 return; 1648 return;
1685 } 1649 }
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
1899 1863
1900 final Socket _socket; 1864 final Socket _socket;
1901 final _HttpServer _httpServer; 1865 final _HttpServer _httpServer;
1902 final _HttpParser _httpParser; 1866 final _HttpParser _httpParser;
1903 StreamSubscription _subscription; 1867 StreamSubscription _subscription;
1904 Timer _idleTimer; 1868 Timer _idleTimer;
1905 final Uint8List _headersBuffer = new Uint8List(_HEADERS_BUFFER_SIZE); 1869 final Uint8List _headersBuffer = new Uint8List(_HEADERS_BUFFER_SIZE);
1906 1870
1907 Future _streamFuture; 1871 Future _streamFuture;
1908 1872
1909 _HttpConnection(Socket this._socket, _HttpServer this._httpServer) 1873 _HttpConnection(this._socket, this._httpServer)
1910 : _httpParser = new _HttpParser.requestParser() { 1874 : _httpParser = new _HttpParser.requestParser() {
1911 _startTimeout(); 1875 _startTimeout();
1912 _socket.pipe(_httpParser); 1876 _socket.pipe(_httpParser);
1913 _subscription = _httpParser.listen( 1877 _subscription = _httpParser.listen(
1914 (incoming) { 1878 (incoming) {
1915 _stopTimeout(); 1879 _stopTimeout();
1916 // If the incoming was closed, close the connection. 1880 // If the incoming was closed, close the connection.
1917 incoming.dataDone.then((closing) { 1881 incoming.dataDone.then((closing) {
1918 if (closing) destroy(); 1882 if (closing) destroy();
1919 }); 1883 });
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
2032 .then((socket) { 1996 .then((socket) {
2033 return new _HttpServer._(socket, true); 1997 return new _HttpServer._(socket, true);
2034 }); 1998 });
2035 } 1999 }
2036 2000
2037 _HttpServer._(this._serverSocket, this._closeServer) { 2001 _HttpServer._(this._serverSocket, this._closeServer) {
2038 _controller = new StreamController<HttpRequest>(sync: true, 2002 _controller = new StreamController<HttpRequest>(sync: true,
2039 onCancel: close); 2003 onCancel: close);
2040 } 2004 }
2041 2005
2042 _HttpServer.listenOn(ServerSocket this._serverSocket) 2006 _HttpServer.listenOn(this._serverSocket) : _closeServer = false {
2043 : _closeServer = false {
2044 _controller = new StreamController<HttpRequest>(sync: true, 2007 _controller = new StreamController<HttpRequest>(sync: true,
2045 onCancel: close); 2008 onCancel: close);
2046 } 2009 }
2047 2010
2048 StreamSubscription<HttpRequest> listen(void onData(HttpRequest event), 2011 StreamSubscription<HttpRequest> listen(void onData(HttpRequest event),
2049 {Function onError, 2012 {Function onError,
2050 void onDone(), 2013 void onDone(),
2051 bool cancelOnError}) { 2014 bool cancelOnError}) {
2052 _serverSocket.listen( 2015 _serverSocket.listen(
2053 (Socket socket) { 2016 (Socket socket) {
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
2108 2071
2109 InternetAddress get address { 2072 InternetAddress get address {
2110 if (closed) throw new HttpException("HttpServer is not bound to a socket"); 2073 if (closed) throw new HttpException("HttpServer is not bound to a socket");
2111 return _serverSocket.address; 2074 return _serverSocket.address;
2112 } 2075 }
2113 2076
2114 set sessionTimeout(int timeout) { 2077 set sessionTimeout(int timeout) {
2115 _sessionManager.sessionTimeout = timeout; 2078 _sessionManager.sessionTimeout = timeout;
2116 } 2079 }
2117 2080
2118 void _handleRequest(HttpRequest request) { 2081 void _handleRequest(HttpRequest request) => _controller.add(request);
2119 _controller.add(request);
2120 }
2121 2082
2122 void _handleError(error) { 2083 void _handleError(error) {
2123 if (!closed) _controller.addError(error); 2084 if (!closed) _controller.addError(error);
2124 } 2085 }
2125 2086
2126 void _connectionClosed(_HttpConnection connection) { 2087 void _connectionClosed(_HttpConnection connection) {
2127 _connections.remove(connection); 2088 _connections.remove(connection);
2128 _maybeCloseSessionManager(); 2089 _maybeCloseSessionManager();
2129 } 2090 }
2130 2091
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
2230 } 2191 }
2231 2192
2232 const _ProxyConfiguration.direct() 2193 const _ProxyConfiguration.direct()
2233 : proxies = const [const _Proxy.direct()]; 2194 : proxies = const [const _Proxy.direct()];
2234 2195
2235 final List<_Proxy> proxies; 2196 final List<_Proxy> proxies;
2236 } 2197 }
2237 2198
2238 2199
2239 class _Proxy { 2200 class _Proxy {
2240 const _Proxy(
2241 this.host, this.port, this.username, this.password) : isDirect = false;
2242 const _Proxy.direct() : host = null, port = null,
2243 username = null, password = null, isDirect = true;
2244
2245 bool get isAuthenticated => username != null;
2246
2247 final String host; 2201 final String host;
2248 final int port; 2202 final int port;
2249 final String username; 2203 final String username;
2250 final String password; 2204 final String password;
2251 final bool isDirect; 2205 final bool isDirect;
2206
2207 const _Proxy(this.host, this.port, this.username, this.password)
2208 : isDirect = false;
2209 const _Proxy.direct() : host = null, port = null,
2210 username = null, password = null, isDirect = true;
2211
2212 bool get isAuthenticated => username != null;
2252 } 2213 }
2253 2214
2254 2215
2255 class _HttpConnectionInfo implements HttpConnectionInfo { 2216 class _HttpConnectionInfo implements HttpConnectionInfo {
2217 InternetAddress remoteAddress;
2218 int remotePort;
2219 int localPort;
2220
2256 static _HttpConnectionInfo create(Socket socket) { 2221 static _HttpConnectionInfo create(Socket socket) {
2257 if (socket == null) return null; 2222 if (socket == null) return null;
2258 try { 2223 try {
2259 _HttpConnectionInfo info = new _HttpConnectionInfo(); 2224 _HttpConnectionInfo info = new _HttpConnectionInfo();
2260 info.remoteAddress = socket.remoteAddress; 2225 return info
2261 info.remotePort = socket.remotePort; 2226 ..remoteAddress = socket.remoteAddress
2262 info.localPort = socket.port; 2227 ..remotePort = socket.remotePort
2263 return info; 2228 ..localPort = socket.port;
2264 } catch (e) { } 2229 } catch (e) { }
2265 return null; 2230 return null;
2266 } 2231 }
2267
2268 InternetAddress remoteAddress;
2269 int remotePort;
2270 int localPort;
2271 } 2232 }
2272 2233
2273 2234
2274 class _DetachedSocket extends Stream<List<int>> implements Socket { 2235 class _DetachedSocket extends Stream<List<int>> implements Socket {
2275 final Stream<List<int>> _incoming; 2236 final Stream<List<int>> _incoming;
2276 final Socket _socket; 2237 final Socket _socket;
2277 2238
2278 _DetachedSocket(this._socket, this._incoming); 2239 _DetachedSocket(this._socket, this._incoming);
2279 2240
2280 StreamSubscription<List<int>> listen(void onData(List<int> event), 2241 StreamSubscription<List<int>> listen(void onData(List<int> event),
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
2328 2289
2329 int get remotePort => _socket.remotePort; 2290 int get remotePort => _socket.remotePort;
2330 2291
2331 bool setOption(SocketOption option, bool enabled) { 2292 bool setOption(SocketOption option, bool enabled) {
2332 return _socket.setOption(option, enabled); 2293 return _socket.setOption(option, enabled);
2333 } 2294 }
2334 } 2295 }
2335 2296
2336 2297
2337 class _AuthenticationScheme { 2298 class _AuthenticationScheme {
2299 final int _scheme;
2300
2338 static const UNKNOWN = const _AuthenticationScheme(-1); 2301 static const UNKNOWN = const _AuthenticationScheme(-1);
2339 static const BASIC = const _AuthenticationScheme(0); 2302 static const BASIC = const _AuthenticationScheme(0);
2340 static const DIGEST = const _AuthenticationScheme(1); 2303 static const DIGEST = const _AuthenticationScheme(1);
2341 2304
2342 const _AuthenticationScheme(this._scheme); 2305 const _AuthenticationScheme(this._scheme);
2343 2306
2344 factory _AuthenticationScheme.fromString(String scheme) { 2307 factory _AuthenticationScheme.fromString(String scheme) {
2345 if (scheme.toLowerCase() == "basic") return BASIC; 2308 if (scheme.toLowerCase() == "basic") return BASIC;
2346 if (scheme.toLowerCase() == "digest") return DIGEST; 2309 if (scheme.toLowerCase() == "digest") return DIGEST;
2347 return UNKNOWN; 2310 return UNKNOWN;
2348 } 2311 }
2349 2312
2350 String toString() { 2313 String toString() {
2351 if (this == BASIC) return "Basic"; 2314 if (this == BASIC) return "Basic";
2352 if (this == DIGEST) return "Digest"; 2315 if (this == DIGEST) return "Digest";
2353 return "Unknown"; 2316 return "Unknown";
2354 } 2317 }
2355
2356 final int _scheme;
2357 } 2318 }
2358 2319
2359 2320
2360 abstract class _Credentials { 2321 abstract class _Credentials {
2361 _HttpClientCredentials credentials; 2322 _HttpClientCredentials credentials;
2362 String realm; 2323 String realm;
2363 bool used = false; 2324 bool used = false;
2364 2325
2365 // Digest specific fields. 2326 // Digest specific fields.
2366 String ha1; 2327 String ha1;
2367 String nonce; 2328 String nonce;
2368 String algorithm; 2329 String algorithm;
2369 String qop; 2330 String qop;
2370 int nonceCount; 2331 int nonceCount;
2371 2332
2372 _Credentials(this.credentials, this.realm) { 2333 _Credentials(this.credentials, this.realm) {
2373 if (credentials.scheme == _AuthenticationScheme.DIGEST) { 2334 if (credentials.scheme == _AuthenticationScheme.DIGEST) {
2374 // Calculate the H(A1) value once. There is no mentioning of 2335 // Calculate the H(A1) value once. There is no mentioning of
2375 // username/password encoding in RFC 2617. However there is an 2336 // username/password encoding in RFC 2617. However there is an
2376 // open draft for adding an additional accept-charset parameter to 2337 // open draft for adding an additional accept-charset parameter to
2377 // the WWW-Authenticate and Proxy-Authenticate headers, see 2338 // the WWW-Authenticate and Proxy-Authenticate headers, see
2378 // http://tools.ietf.org/html/draft-reschke-basicauth-enc-06. For 2339 // http://tools.ietf.org/html/draft-reschke-basicauth-enc-06. For
2379 // now always use UTF-8 encoding. 2340 // now always use UTF-8 encoding.
2380 _HttpClientDigestCredentials creds = credentials; 2341 _HttpClientDigestCredentials creds = credentials;
2381 var hasher = new _MD5(); 2342 var hasher = new _MD5()
2382 hasher.add(UTF8.encode(creds.username)); 2343 ..add(UTF8.encode(creds.username))
2383 hasher.add([_CharCode.COLON]); 2344 ..add([_CharCode.COLON])
2384 hasher.add(realm.codeUnits); 2345 ..add(realm.codeUnits)
2385 hasher.add([_CharCode.COLON]); 2346 ..add([_CharCode.COLON])
2386 hasher.add(UTF8.encode(creds.password)); 2347 ..add(UTF8.encode(creds.password));
2387 ha1 = _CryptoUtils.bytesToHex(hasher.close()); 2348 ha1 = _CryptoUtils.bytesToHex(hasher.close());
2388 } 2349 }
2389 } 2350 }
2390 2351
2391 _AuthenticationScheme get scheme => credentials.scheme; 2352 _AuthenticationScheme get scheme => credentials.scheme;
2392 2353
2393 void authorize(HttpClientRequest request); 2354 void authorize(HttpClientRequest request);
2394 } 2355 }
2395 2356
2396 class _SiteCredentials extends _Credentials { 2357 class _SiteCredentials extends _Credentials {
2397 Uri uri; 2358 Uri uri;
2398 2359
2399 _SiteCredentials(this.uri, realm, _HttpClientCredentials creds) 2360 _SiteCredentials(this.uri, realm, _HttpClientCredentials creds)
2400 : super(creds, realm); 2361 : super(creds, realm);
2401 2362
2402 bool applies(Uri uri, _AuthenticationScheme scheme) { 2363 bool applies(Uri uri, _AuthenticationScheme scheme) {
2403 if (scheme != null && credentials.scheme != scheme) return false; 2364 if (scheme != null && credentials.scheme != scheme) return false;
2404 if (uri.host != this.uri.host) return false; 2365 if (uri.host != this.uri.host) return false;
2405 int thisPort = 2366 int thisPort =
2406 this.uri.port == 0 ? HttpClient.DEFAULT_HTTP_PORT : this.uri.port; 2367 this.uri.port == 0 ? HttpClient.DEFAULT_HTTP_PORT : this.uri.port;
2407 int otherPort = uri.port == 0 ? HttpClient.DEFAULT_HTTP_PORT : uri.port; 2368 int otherPort = uri.port == 0 ? HttpClient.DEFAULT_HTTP_PORT : uri.port;
2408 if (otherPort != thisPort) return false; 2369 if (otherPort != thisPort) return false;
2409 return uri.path.startsWith(this.uri.path); 2370 return uri.path.startsWith(this.uri.path);
2410 } 2371 }
(...skipping 12 matching lines...) Expand all
2423 2384
2424 2385
2425 class _ProxyCredentials extends _Credentials { 2386 class _ProxyCredentials extends _Credentials {
2426 String host; 2387 String host;
2427 int port; 2388 int port;
2428 2389
2429 _ProxyCredentials(this.host, 2390 _ProxyCredentials(this.host,
2430 this.port, 2391 this.port,
2431 realm, 2392 realm,
2432 _HttpClientCredentials creds) 2393 _HttpClientCredentials creds)
2433 : super(creds, realm); 2394 : super(creds, realm);
2434 2395
2435 bool applies(_Proxy proxy, _AuthenticationScheme scheme) { 2396 bool applies(_Proxy proxy, _AuthenticationScheme scheme) {
2436 if (scheme != null && credentials.scheme != scheme) return false; 2397 if (scheme != null && credentials.scheme != scheme) return false;
2437 return proxy.host == host && proxy.port == port; 2398 return proxy.host == host && proxy.port == port;
2438 } 2399 }
2439 2400
2440 void authorize(HttpClientRequest request) { 2401 void authorize(HttpClientRequest request) {
2441 // Digest credentials cannot be used without a nonce from the 2402 // Digest credentials cannot be used without a nonce from the
2442 // server. 2403 // server.
2443 if (credentials.scheme == _AuthenticationScheme.DIGEST && 2404 if (credentials.scheme == _AuthenticationScheme.DIGEST &&
2444 nonce == null) { 2405 nonce == null) {
2445 return; 2406 return;
2446 } 2407 }
2447 credentials.authorizeProxy(this, request); 2408 credentials.authorizeProxy(this, request);
2448 } 2409 }
2449 } 2410 }
2450 2411
2451 2412
2452 abstract class _HttpClientCredentials implements HttpClientCredentials { 2413 abstract class _HttpClientCredentials implements HttpClientCredentials {
2453 _AuthenticationScheme get scheme; 2414 _AuthenticationScheme get scheme;
2454 void authorize(_Credentials credentials, HttpClientRequest request); 2415 void authorize(_Credentials credentials, HttpClientRequest request);
2455 void authorizeProxy(_ProxyCredentials credentials, HttpClientRequest request); 2416 void authorizeProxy(_ProxyCredentials credentials, HttpClientRequest request);
2456 } 2417 }
2457 2418
2458 2419
2459 class _HttpClientBasicCredentials 2420 class _HttpClientBasicCredentials
2460 extends _HttpClientCredentials 2421 extends _HttpClientCredentials
2461 implements HttpClientBasicCredentials { 2422 implements HttpClientBasicCredentials {
2462 _HttpClientBasicCredentials(this.username, 2423 String username;
2463 this.password); 2424 String password;
2425
2426 _HttpClientBasicCredentials(this.username, this.password);
2464 2427
2465 _AuthenticationScheme get scheme => _AuthenticationScheme.BASIC; 2428 _AuthenticationScheme get scheme => _AuthenticationScheme.BASIC;
2466 2429
2467 String authorization() { 2430 String authorization() {
2468 // There is no mentioning of username/password encoding in RFC 2431 // There is no mentioning of username/password encoding in RFC
2469 // 2617. However there is an open draft for adding an additional 2432 // 2617. However there is an open draft for adding an additional
2470 // accept-charset parameter to the WWW-Authenticate and 2433 // accept-charset parameter to the WWW-Authenticate and
2471 // Proxy-Authenticate headers, see 2434 // Proxy-Authenticate headers, see
2472 // http://tools.ietf.org/html/draft-reschke-basicauth-enc-06. For 2435 // http://tools.ietf.org/html/draft-reschke-basicauth-enc-06. For
2473 // now always use UTF-8 encoding. 2436 // now always use UTF-8 encoding.
2474 String auth = 2437 String auth =
2475 _CryptoUtils.bytesToBase64(UTF8.encode("$username:$password")); 2438 _CryptoUtils.bytesToBase64(UTF8.encode("$username:$password"));
2476 return "Basic $auth"; 2439 return "Basic $auth";
2477 } 2440 }
2478 2441
2479 void authorize(_Credentials _, HttpClientRequest request) { 2442 void authorize(_Credentials _, HttpClientRequest request) =>
2480 request.headers.set(HttpHeaders.AUTHORIZATION, authorization()); 2443 request.headers.set(HttpHeaders.AUTHORIZATION, authorization());
2481 }
2482 2444
2483 void authorizeProxy(_ProxyCredentials _, HttpClientRequest request) { 2445 void authorizeProxy(_ProxyCredentials _, HttpClientRequest request) =>
2484 request.headers.set(HttpHeaders.PROXY_AUTHORIZATION, authorization()); 2446 request.headers.set(HttpHeaders.PROXY_AUTHORIZATION, authorization());
2485 }
2486
2487 String username;
2488 String password;
2489 } 2447 }
2490 2448
2491 2449
2492 class _HttpClientDigestCredentials 2450 class _HttpClientDigestCredentials
2493 extends _HttpClientCredentials 2451 extends _HttpClientCredentials
2494 implements HttpClientDigestCredentials { 2452 implements HttpClientDigestCredentials {
2495 _HttpClientDigestCredentials(this.username, 2453 String username;
2496 this.password); 2454 String password;
2455
2456 _HttpClientDigestCredentials(this.username, this.password);
2497 2457
2498 _AuthenticationScheme get scheme => _AuthenticationScheme.DIGEST; 2458 _AuthenticationScheme get scheme => _AuthenticationScheme.DIGEST;
2499 2459
2500 String authorization(_Credentials credentials, _HttpClientRequest request) { 2460 String authorization(_Credentials credentials, _HttpClientRequest request) {
2501 String requestUri = request._requestUri(); 2461 String requestUri = request._requestUri();
2502 _MD5 hasher = new _MD5(); 2462 _MD5 hasher = new _MD5()
Anders Johnsen 2014/01/06 14:01:53 Indentation, and below.
2503 hasher.add(request.method.codeUnits); 2463 ..add(request.method.codeUnits)
2504 hasher.add([_CharCode.COLON]); 2464 ..add([_CharCode.COLON])
2505 hasher.add(requestUri.codeUnits); 2465 ..add(requestUri.codeUnits);
2506 var ha2 = _CryptoUtils.bytesToHex(hasher.close()); 2466 var ha2 = _CryptoUtils.bytesToHex(hasher.close());
2507 2467
2508 String qop; 2468 String qop;
2509 String cnonce; 2469 String cnonce;
2510 String nc; 2470 String nc;
2511 var x; 2471 var x;
2512 hasher = new _MD5(); 2472 hasher = new _MD5()
2513 hasher.add(credentials.ha1.codeUnits); 2473 ..add(credentials.ha1.codeUnits)
2514 hasher.add([_CharCode.COLON]); 2474 ..add([_CharCode.COLON]);
2515 if (credentials.qop == "auth") { 2475 if (credentials.qop == "auth") {
2516 qop = credentials.qop; 2476 qop = credentials.qop;
2517 cnonce = _CryptoUtils.bytesToHex(_IOCrypto.getRandomBytes(4)); 2477 cnonce = _CryptoUtils.bytesToHex(_IOCrypto.getRandomBytes(4));
2518 ++credentials.nonceCount; 2478 ++credentials.nonceCount;
2519 nc = credentials.nonceCount.toRadixString(16); 2479 nc = credentials.nonceCount.toRadixString(16);
2520 nc = "00000000".substring(0, 8 - nc.length + 1) + nc; 2480 nc = "00000000".substring(0, 8 - nc.length + 1) + nc;
2521 hasher.add(credentials.nonce.codeUnits); 2481 hasher
2522 hasher.add([_CharCode.COLON]); 2482 ..add(credentials.nonce.codeUnits)
2523 hasher.add(nc.codeUnits); 2483 ..add([_CharCode.COLON])
2524 hasher.add([_CharCode.COLON]); 2484 ..add(nc.codeUnits)
2525 hasher.add(cnonce.codeUnits); 2485 ..add([_CharCode.COLON])
2526 hasher.add([_CharCode.COLON]); 2486 ..add(cnonce.codeUnits)
2527 hasher.add(credentials.qop.codeUnits); 2487 ..add([_CharCode.COLON])
2528 hasher.add([_CharCode.COLON]); 2488 ..add(credentials.qop.codeUnits)
2529 hasher.add(ha2.codeUnits); 2489 ..add([_CharCode.COLON])
2490 ..add(ha2.codeUnits);
2530 } else { 2491 } else {
2531 hasher.add(credentials.nonce.codeUnits); 2492 hasher
2532 hasher.add([_CharCode.COLON]); 2493 ..add(credentials.nonce.codeUnits)
2533 hasher.add(ha2.codeUnits); 2494 ..add([_CharCode.COLON])
2495 ..add(ha2.codeUnits);
2534 } 2496 }
2535 var response = _CryptoUtils.bytesToHex(hasher.close()); 2497 var response = _CryptoUtils.bytesToHex(hasher.close());
2536 2498
2537 StringBuffer buffer = new StringBuffer(); 2499 StringBuffer buffer = new StringBuffer()
2538 buffer.write('Digest '); 2500 ..write('Digest ')
2539 buffer.write('username="$username"'); 2501 ..write('username="$username"')
2540 buffer.write(', realm="${credentials.realm}"'); 2502 ..write(', realm="${credentials.realm}"')
2541 buffer.write(', nonce="${credentials.nonce}"'); 2503 ..write(', nonce="${credentials.nonce}"')
2542 buffer.write(', uri="$requestUri"'); 2504 ..write(', uri="$requestUri"')
2543 buffer.write(', algorithm="${credentials.algorithm}"'); 2505 ..write(', algorithm="${credentials.algorithm}"');
2544 if (qop == "auth") { 2506 if (qop == "auth") {
2545 buffer.write(', qop="$qop"'); 2507 buffer
2546 buffer.write(', cnonce="$cnonce"'); 2508 ..write(', qop="$qop"')
2547 buffer.write(', nc="$nc"'); 2509 ..write(', cnonce="$cnonce"')
2510 ..write(', nc="$nc"');
2548 } 2511 }
2549 buffer.write(', response="$response"'); 2512 buffer.write(', response="$response"');
2550 return buffer.toString(); 2513 return buffer.toString();
2551 } 2514 }
2552 2515
2553 void authorize(_Credentials credentials, HttpClientRequest request) { 2516 void authorize(_Credentials credentials, HttpClientRequest request) {
2554 request.headers.set(HttpHeaders.AUTHORIZATION, 2517 request.headers.set(HttpHeaders.AUTHORIZATION,
2555 authorization(credentials, request)); 2518 authorization(credentials, request));
2556 } 2519 }
2557 2520
2558 void authorizeProxy(_ProxyCredentials credentials, 2521 void authorizeProxy(_ProxyCredentials credentials,
2559 HttpClientRequest request) { 2522 HttpClientRequest request) {
2560 request.headers.set(HttpHeaders.PROXY_AUTHORIZATION, 2523 request.headers.set(HttpHeaders.PROXY_AUTHORIZATION,
2561 authorization(credentials, request)); 2524 authorization(credentials, request));
2562 } 2525 }
2563
2564 String username;
2565 String password;
2566 } 2526 }
2567 2527
2568 2528
2569 class _RedirectInfo implements RedirectInfo { 2529 class _RedirectInfo implements RedirectInfo {
2570 const _RedirectInfo(int this.statusCode,
2571 String this.method,
2572 Uri this.location);
2573 final int statusCode; 2530 final int statusCode;
2574 final String method; 2531 final String method;
2575 final Uri location; 2532 final Uri location;
2533 const _RedirectInfo(this.statusCode, this.method, this.location);
2576 } 2534 }
2577 2535
2578 String _getHttpVersion() { 2536 String _getHttpVersion() {
2579 var version = Platform.version; 2537 var version = Platform.version;
2580 // Only include major and minor version numbers. 2538 // Only include major and minor version numbers.
2581 int index = version.indexOf('.', version.indexOf('.') + 1); 2539 int index = version.indexOf('.', version.indexOf('.') + 1);
2582 version = version.substring(0, index); 2540 version = version.substring(0, index);
2583 return 'Dart/$version (dart:io)'; 2541 return 'Dart/$version (dart:io)';
2584 } 2542 }
2585
2586
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698