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

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

Powered by Google App Engine
This is Rietveld 408576698