OLD | NEW |
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 class _HttpIncoming extends Stream<List<int>> { | 7 class _HttpIncoming extends Stream<List<int>> { |
8 final int _transferLength; | 8 final int _transferLength; |
9 final Completer _dataCompleter = new Completer(); | 9 final Completer _dataCompleter = new Completer(); |
10 Stream<List<int>> _stream; | 10 Stream<List<int>> _stream; |
(...skipping 658 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
669 | 669 |
670 | 670 |
671 class _HttpResponse extends _HttpOutboundMessage<HttpResponse> | 671 class _HttpResponse extends _HttpOutboundMessage<HttpResponse> |
672 implements HttpResponse { | 672 implements HttpResponse { |
673 int statusCode = 200; | 673 int statusCode = 200; |
674 String _reasonPhrase; | 674 String _reasonPhrase; |
675 List<Cookie> _cookies; | 675 List<Cookie> _cookies; |
676 _HttpRequest _httpRequest; | 676 _HttpRequest _httpRequest; |
677 | 677 |
678 _HttpResponse(String protocolVersion, | 678 _HttpResponse(String protocolVersion, |
679 _HttpOutgoing _outgoing) | 679 _HttpOutgoing _outgoing, |
680 : super(protocolVersion, _outgoing); | 680 String serverHeader) |
| 681 : super(protocolVersion, _outgoing) { |
| 682 if (serverHeader != null) headers.set('Server', serverHeader); |
| 683 } |
681 | 684 |
682 List<Cookie> get cookies { | 685 List<Cookie> get cookies { |
683 if (_cookies == null) _cookies = new List<Cookie>(); | 686 if (_cookies == null) _cookies = new List<Cookie>(); |
684 return _cookies; | 687 return _cookies; |
685 } | 688 } |
686 | 689 |
687 String get reasonPhrase => _findReasonPhrase(statusCode); | 690 String get reasonPhrase => _findReasonPhrase(statusCode); |
688 void set reasonPhrase(String reasonPhrase) { | 691 void set reasonPhrase(String reasonPhrase) { |
689 if (_headersWritten) throw new StateError("Header already sent"); | 692 if (_headersWritten) throw new StateError("Header already sent"); |
690 _reasonPhrase = reasonPhrase; | 693 _reasonPhrase = reasonPhrase; |
(...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1142 // Create new request object, wrapping the outgoing connection. | 1145 // Create new request object, wrapping the outgoing connection. |
1143 var request = new _HttpClientRequest(outgoing, | 1146 var request = new _HttpClientRequest(outgoing, |
1144 uri, | 1147 uri, |
1145 method, | 1148 method, |
1146 proxy, | 1149 proxy, |
1147 _httpClient, | 1150 _httpClient, |
1148 this); | 1151 this); |
1149 request.headers.host = uri.host; | 1152 request.headers.host = uri.host; |
1150 request.headers.port = port; | 1153 request.headers.port = port; |
1151 request.headers.set(HttpHeaders.ACCEPT_ENCODING, "gzip"); | 1154 request.headers.set(HttpHeaders.ACCEPT_ENCODING, "gzip"); |
| 1155 if (_httpClient.userAgent != null) { |
| 1156 request.headers.set('User-Agent', _httpClient.userAgent); |
| 1157 } |
1152 if (proxy.isAuthenticated) { | 1158 if (proxy.isAuthenticated) { |
1153 // If the proxy configuration contains user information use that | 1159 // If the proxy configuration contains user information use that |
1154 // for proxy basic authorization. | 1160 // for proxy basic authorization. |
1155 String auth = _CryptoUtils.bytesToBase64( | 1161 String auth = _CryptoUtils.bytesToBase64( |
1156 _encodeString("${proxy.username}:${proxy.password}")); | 1162 _encodeString("${proxy.username}:${proxy.password}")); |
1157 request.headers.set(HttpHeaders.PROXY_AUTHORIZATION, "Basic $auth"); | 1163 request.headers.set(HttpHeaders.PROXY_AUTHORIZATION, "Basic $auth"); |
1158 } else if (!proxy.isDirect && _httpClient._proxyCredentials.length > 0) { | 1164 } else if (!proxy.isDirect && _httpClient._proxyCredentials.length > 0) { |
1159 proxyCreds = _httpClient._findProxyCredentials(proxy); | 1165 proxyCreds = _httpClient._findProxyCredentials(proxy); |
1160 if (proxyCreds != null) { | 1166 if (proxyCreds != null) { |
1161 proxyCreds.authorize(request); | 1167 proxyCreds.authorize(request); |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1339 final List<_ProxyCredentials> _proxyCredentials = []; | 1345 final List<_ProxyCredentials> _proxyCredentials = []; |
1340 Function _authenticate; | 1346 Function _authenticate; |
1341 Function _authenticateProxy; | 1347 Function _authenticateProxy; |
1342 Function _findProxy = HttpClient.findProxyFromEnvironment; | 1348 Function _findProxy = HttpClient.findProxyFromEnvironment; |
1343 Duration _idleTimeout = const Duration(seconds: 15); | 1349 Duration _idleTimeout = const Duration(seconds: 15); |
1344 | 1350 |
1345 Timer _noActiveTimer; | 1351 Timer _noActiveTimer; |
1346 | 1352 |
1347 Duration get idleTimeout => _idleTimeout; | 1353 Duration get idleTimeout => _idleTimeout; |
1348 | 1354 |
| 1355 String userAgent = _getHttpVersion(); |
| 1356 |
1349 void set idleTimeout(Duration timeout) { | 1357 void set idleTimeout(Duration timeout) { |
1350 _idleTimeout = timeout; | 1358 _idleTimeout = timeout; |
1351 _idleConnections.values.forEach( | 1359 _idleConnections.values.forEach( |
1352 (l) => l.forEach((c) { | 1360 (l) => l.forEach((c) { |
1353 // Reset timer. This is fine, as it's not happening often. | 1361 // Reset timer. This is fine, as it's not happening often. |
1354 c.stopTimer(); | 1362 c.stopTimer(); |
1355 c.startTimer(); | 1363 c.startTimer(); |
1356 })); | 1364 })); |
1357 } | 1365 } |
1358 | 1366 |
| 1367 |
1359 Future<HttpClientRequest> open(String method, | 1368 Future<HttpClientRequest> open(String method, |
1360 String host, | 1369 String host, |
1361 int port, | 1370 int port, |
1362 String path) { | 1371 String path) { |
1363 // TODO(sgjesse): The path set here can contain both query and | 1372 // TODO(sgjesse): The path set here can contain both query and |
1364 // fragment. They should be cracked and set correctly. | 1373 // fragment. They should be cracked and set correctly. |
1365 return _openUrl(method, new Uri( | 1374 return _openUrl(method, new Uri( |
1366 scheme: "http", host: host, port: port, path: path)); | 1375 scheme: "http", host: host, port: port, path: path)); |
1367 } | 1376 } |
1368 | 1377 |
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1748 // If the incoming was closed, close the connection. | 1757 // If the incoming was closed, close the connection. |
1749 incoming.dataDone.then((closing) { | 1758 incoming.dataDone.then((closing) { |
1750 if (closing) destroy(); | 1759 if (closing) destroy(); |
1751 }); | 1760 }); |
1752 // Only handle one incoming request at the time. Keep the | 1761 // Only handle one incoming request at the time. Keep the |
1753 // stream paused until the request has been send. | 1762 // stream paused until the request has been send. |
1754 _subscription.pause(); | 1763 _subscription.pause(); |
1755 _state = _ACTIVE; | 1764 _state = _ACTIVE; |
1756 var outgoing = new _HttpOutgoing(_socket); | 1765 var outgoing = new _HttpOutgoing(_socket); |
1757 var response = new _HttpResponse(incoming.headers.protocolVersion, | 1766 var response = new _HttpResponse(incoming.headers.protocolVersion, |
1758 outgoing); | 1767 outgoing, |
| 1768 _httpServer.serverHeader); |
1759 var request = new _HttpRequest(response, incoming, _httpServer, this); | 1769 var request = new _HttpRequest(response, incoming, _httpServer, this); |
1760 _streamFuture = outgoing.done | 1770 _streamFuture = outgoing.done |
1761 .then((_) { | 1771 .then((_) { |
1762 if (_state == _DETACHED) return; | 1772 if (_state == _DETACHED) return; |
1763 if (response.persistentConnection && | 1773 if (response.persistentConnection && |
1764 request.persistentConnection && | 1774 request.persistentConnection && |
1765 incoming.fullBodyRead) { | 1775 incoming.fullBodyRead) { |
1766 _state = _IDLE; | 1776 _state = _IDLE; |
1767 // Resume the subscription for incoming requests as the | 1777 // Resume the subscription for incoming requests as the |
1768 // request is now processed. | 1778 // request is now processed. |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1812 | 1822 |
1813 bool get _isActive => _state == _ACTIVE; | 1823 bool get _isActive => _state == _ACTIVE; |
1814 bool get _isIdle => _state == _IDLE; | 1824 bool get _isIdle => _state == _IDLE; |
1815 bool get _isClosing => _state == _CLOSING; | 1825 bool get _isClosing => _state == _CLOSING; |
1816 bool get _isDetached => _state == _DETACHED; | 1826 bool get _isDetached => _state == _DETACHED; |
1817 } | 1827 } |
1818 | 1828 |
1819 | 1829 |
1820 // HTTP server waiting for socket connections. | 1830 // HTTP server waiting for socket connections. |
1821 class _HttpServer extends Stream<HttpRequest> implements HttpServer { | 1831 class _HttpServer extends Stream<HttpRequest> implements HttpServer { |
| 1832 String serverHeader = _getHttpVersion(); |
1822 | 1833 |
1823 static Future<HttpServer> bind(address, int port, int backlog) { | 1834 static Future<HttpServer> bind(address, int port, int backlog) { |
1824 return ServerSocket.bind(address, port, backlog: backlog).then((socket) { | 1835 return ServerSocket.bind(address, port, backlog: backlog).then((socket) { |
1825 return new _HttpServer._(socket, true); | 1836 return new _HttpServer._(socket, true); |
1826 }); | 1837 }); |
1827 } | 1838 } |
1828 | 1839 |
1829 static Future<HttpServer> bindSecure(address, | 1840 static Future<HttpServer> bindSecure(address, |
1830 int port, | 1841 int port, |
1831 int backlog, | 1842 int backlog, |
(...skipping 510 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2342 | 2353 |
2343 | 2354 |
2344 class _RedirectInfo implements RedirectInfo { | 2355 class _RedirectInfo implements RedirectInfo { |
2345 const _RedirectInfo(int this.statusCode, | 2356 const _RedirectInfo(int this.statusCode, |
2346 String this.method, | 2357 String this.method, |
2347 Uri this.location); | 2358 Uri this.location); |
2348 final int statusCode; | 2359 final int statusCode; |
2349 final String method; | 2360 final String method; |
2350 final Uri location; | 2361 final Uri location; |
2351 } | 2362 } |
| 2363 |
| 2364 String _getHttpVersion() { |
| 2365 var version = new Options().version; |
| 2366 // Only include major and minor version numbers. |
| 2367 int index = version.indexOf('.', version.indexOf('.') + 1); |
| 2368 version = version.substring(0, index); |
| 2369 return 'Dart/$version (dart:io)'; |
| 2370 } |
OLD | NEW |