Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 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 class _HttpRequestResponseBase { | 5 class _HttpRequestResponseBase { |
| 6 _HttpRequestResponseBase(_HttpConnectionBase this._httpConnection) | 6 _HttpRequestResponseBase(_HttpConnectionBase this._httpConnection) |
| 7 : _contentLength = -1, | 7 : _contentLength = -1, |
| 8 _keepAlive = false, | 8 _keepAlive = false, |
| 9 _headers = new Map(); | 9 _headers = new Map(); |
| 10 | 10 |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 253 if (_outputStream == null) { | 253 if (_outputStream == null) { |
| 254 // Ensure that headers are written. | 254 // Ensure that headers are written. |
| 255 if (_state == START) { | 255 if (_state == START) { |
| 256 _writeHeader(); | 256 _writeHeader(); |
| 257 } | 257 } |
| 258 _outputStream = new _HttpOutputStream(this); | 258 _outputStream = new _HttpOutputStream(this); |
| 259 } | 259 } |
| 260 return _outputStream; | 260 return _outputStream; |
| 261 } | 261 } |
| 262 | 262 |
| 263 void _responseEnd() { | |
| 264 _state = DONE; | |
| 265 // Stop tracking no pending write events. | |
| 266 _httpConnection.outputStream.onNoPendingWrites = null; | |
| 267 // Ensure that any trailing data is written. | |
| 268 _writeDone(); | |
| 269 // Indicate to the connection that the response handling is done. | |
| 270 _httpConnection._responseDone(); | |
| 271 } | |
| 272 | |
| 263 // Delegate functions for the HttpOutputStream implementation. | 273 // Delegate functions for the HttpOutputStream implementation. |
| 264 bool _streamWrite(List<int> buffer, bool copyBuffer) { | 274 bool _streamWrite(List<int> buffer, bool copyBuffer) { |
| 265 return _write(buffer, copyBuffer); | 275 return _write(buffer, copyBuffer); |
| 266 } | 276 } |
| 267 | 277 |
| 268 bool _streamWriteFrom(List<int> buffer, int offset, int len) { | 278 bool _streamWriteFrom(List<int> buffer, int offset, int len) { |
| 269 return _writeList(buffer, offset, len); | 279 return _writeList(buffer, offset, len); |
| 270 } | 280 } |
| 271 | 281 |
| 272 void _streamClose() { | 282 void _streamClose() { |
| 273 _httpConnection._phase = _HttpConnectionBase.PHASE_IDLE; | 283 _responseEnd(); |
| 274 _state = DONE; | |
| 275 // Stop tracking no pending write events. | |
| 276 _httpConnection._onNoPendingWrites = null; | |
| 277 // Ensure that any trailing data is written. | |
| 278 _writeDone(); | |
| 279 // If the connection is closing then close the output stream to | |
| 280 // fully close the socket. | |
| 281 if (_httpConnection._closing) { | |
| 282 _httpConnection._close(); | |
| 283 } | |
| 284 } | 284 } |
| 285 | 285 |
| 286 void _streamSetNoPendingWriteHandler(callback()) { | 286 void _streamSetNoPendingWriteHandler(callback()) { |
| 287 if (_state != DONE) { | 287 if (_state != DONE) { |
| 288 _httpConnection._onNoPendingWrites = callback; | 288 _httpConnection._onNoPendingWrites = callback; |
| 289 } | 289 } |
| 290 } | 290 } |
| 291 | 291 |
| 292 void _streamSetCloseHandler(callback()) { | 292 void _streamSetCloseHandler(callback()) { |
| 293 // TODO(sgjesse): Handle this. | 293 // TODO(sgjesse): Handle this. |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 462 | 462 |
| 463 void set onError(void callback(Exception e)) { | 463 void set onError(void callback(Exception e)) { |
| 464 _requestOrResponse._streamSetErrorHandler(callback); | 464 _requestOrResponse._streamSetErrorHandler(callback); |
| 465 } | 465 } |
| 466 | 466 |
| 467 _HttpRequestResponseBase _requestOrResponse; | 467 _HttpRequestResponseBase _requestOrResponse; |
| 468 } | 468 } |
| 469 | 469 |
| 470 | 470 |
| 471 class _HttpConnectionBase implements Hashable { | 471 class _HttpConnectionBase implements Hashable { |
| 472 static final int PHASE_IDLE = 0; | 472 _HttpConnectionBase() : _sendBuffers = new Queue(), |
| 473 static final int PHASE_REQUEST = 1; | |
| 474 static final int PHASE_RESPONSE = 2; | |
| 475 | |
| 476 _HttpConnectionBase() : _phase = PHASE_IDLE, | |
| 477 _sendBuffers = new Queue(), | |
| 478 _httpParser = new _HttpParser(); | 473 _httpParser = new _HttpParser(); |
| 479 | 474 |
| 480 void _connectionEstablished(Socket socket) { | 475 void _connectionEstablished(Socket socket) { |
| 481 _socket = socket; | 476 _socket = socket; |
| 482 // Register handler for socket events. | 477 // Register handler for socket events. |
| 483 _socket.onData = _onData; | 478 _socket.onData = _onData; |
| 484 _socket.onClosed = _onClosed; | 479 _socket.onClosed = _onClosed; |
| 485 _socket.onError = _onError; | 480 _socket.onError = _onError; |
| 486 } | 481 } |
| 487 | 482 |
| 488 bool _write(List<int> data, [bool copyBuffer = false]) { | 483 bool _write(List<int> data, [bool copyBuffer = false]) { |
| 489 if (!_error) { | 484 if (!_error) { |
|
Anders Johnsen
2012/04/10 08:18:53
I think we should add "&& !_closing".
| |
| 490 return _socket.outputStream.write(data, copyBuffer); | 485 return _socket.outputStream.write(data, copyBuffer); |
| 491 } | 486 } |
| 492 } | 487 } |
| 493 | 488 |
| 494 bool _writeFrom(List<int> buffer, [int offset, int len]) { | 489 bool _writeFrom(List<int> buffer, [int offset, int len]) { |
| 495 if (!_error) { | 490 if (!_error) { |
|
Anders Johnsen
2012/04/10 08:18:53
Same here.
| |
| 496 return _socket.outputStream.writeFrom(buffer, offset, len); | 491 return _socket.outputStream.writeFrom(buffer, offset, len); |
| 497 } | 492 } |
| 498 } | 493 } |
| 499 | 494 |
| 500 bool _close() { | 495 bool _close() { |
| 501 _socket.close(); | 496 _socket.close(); |
| 502 } | 497 } |
| 503 | 498 |
| 504 void _onData() { | 499 void _onData() { |
| 505 int available = _socket.available(); | 500 int available = _socket.available(); |
| 506 if (available == 0) { | 501 if (available == 0) { |
| 507 return; | 502 return; |
| 508 } | 503 } |
| 509 | 504 |
| 510 ByteArray buffer = new ByteArray(available); | 505 ByteArray buffer = new ByteArray(available); |
| 511 int bytesRead = _socket.readList(buffer, 0, available); | 506 int bytesRead = _socket.readList(buffer, 0, available); |
| 512 if (bytesRead > 0) { | 507 if (bytesRead > 0) { |
| 513 int parsed = _httpParser.writeList(buffer, 0, bytesRead); | 508 int parsed = _httpParser.writeList(buffer, 0, bytesRead); |
| 514 if (parsed != bytesRead) { | 509 if (parsed != bytesRead) { |
| 515 // TODO(sgjesse): Error handling. | 510 // TODO(sgjesse): Error handling. |
| 516 _socket.close(); | 511 _socket.close(); |
| 517 } | 512 } |
| 518 } | 513 } |
| 519 } | 514 } |
| 520 | 515 |
| 521 void _onClosed() { | 516 void _onClosed() { |
|
Anders Johnsen
2012/04/10 08:18:53
And a "_closing = true;" here.
| |
| 522 if (_phase != PHASE_IDLE) { | 517 _onConnectionClosed(null); |
| 523 // Client closed socket for writing. Socket should still be open | |
| 524 // for writing the response. | |
| 525 _closing = true; | |
| 526 } else { | |
| 527 // The connection is currently not used by any request just close it. | |
| 528 _socket.close(); | |
| 529 } | |
| 530 if (_onDisconnectCallback != null) _onDisconnectCallback(); | |
| 531 } | 518 } |
| 532 | 519 |
| 533 void _onError(Exception e) { | 520 void _onError(Exception e) { |
| 534 // If an error occurs, make sure to close the socket if one is associated. | 521 // If an error occurs, make sure to close the socket if one is associated. |
| 535 _error = true; | 522 _error = true; |
| 536 if (_socket != null) { | 523 if (_socket != null) { |
| 537 _socket.close(); | 524 _socket.close(); |
| 538 } | 525 } |
| 539 if (_onErrorCallback != null) { | 526 _onConnectionClosed(e); |
| 540 _onErrorCallback(e); | |
| 541 } | |
| 542 _propagateError(e); | |
| 543 } | 527 } |
| 544 | 528 |
| 545 abstract void _propagateError(Exception e); | 529 abstract void _onConnectionClosed(Exception e); |
| 546 | 530 abstract void _responseDone(); |
| 547 void set onDisconnect(void callback()) { | |
| 548 _onDisconnectCallback = callback; | |
| 549 } | |
| 550 | |
| 551 void set onError(void callback(Exception e)) { | |
| 552 _onErrorCallback = callback; | |
| 553 } | |
| 554 | 531 |
| 555 void set _onNoPendingWrites(void callback()) { | 532 void set _onNoPendingWrites(void callback()) { |
| 556 if (!_error) { | 533 if (!_error) { |
| 557 _socket.outputStream.onNoPendingWrites = callback; | 534 _socket.outputStream.onNoPendingWrites = callback; |
| 558 } | 535 } |
| 559 } | 536 } |
| 560 | 537 |
| 561 int hashCode() => _socket.hashCode(); | 538 int hashCode() => _socket.hashCode(); |
| 562 | 539 |
| 563 int _phase; | |
| 564 Socket _socket; | 540 Socket _socket; |
| 565 bool _closing = false; // Is the socket closed by the client? | 541 bool _closing = false; // Is the socket closed by the client? |
| 566 bool _error = false; // Is the socket closed due to an error? | 542 bool _error = false; // Is the socket closed due to an error? |
| 567 _HttpParser _httpParser; | 543 _HttpParser _httpParser; |
| 568 | 544 |
| 569 Queue _sendBuffers; | 545 Queue _sendBuffers; |
| 570 | |
| 571 Function _onDisconnectCallback; | |
| 572 Function _onErrorCallback; | |
| 573 } | 546 } |
| 574 | 547 |
| 575 | 548 |
| 576 // HTTP server connection over a socket. | 549 // HTTP server connection over a socket. |
| 577 class _HttpConnection extends _HttpConnectionBase { | 550 class _HttpConnection extends _HttpConnectionBase { |
| 578 _HttpConnection(HttpServer this._server) { | 551 _HttpConnection(HttpServer this._server) { |
| 579 // Register HTTP parser callbacks. | 552 // Register HTTP parser callbacks. |
| 580 _httpParser.requestStart = | 553 _httpParser.requestStart = |
| 581 (method, uri) => _onRequestStart(method, uri); | 554 (method, uri) => _onRequestStart(method, uri); |
| 582 _httpParser.responseStart = | 555 _httpParser.responseStart = |
| 583 (statusCode, reasonPhrase) => | 556 (statusCode, reasonPhrase) => |
| 584 _onResponseStart(statusCode, reasonPhrase); | 557 _onResponseStart(statusCode, reasonPhrase); |
| 585 _httpParser.headerReceived = | 558 _httpParser.headerReceived = |
| 586 (name, value) => _onHeaderReceived(name, value); | 559 (name, value) => _onHeaderReceived(name, value); |
| 587 _httpParser.headersComplete = () => _onHeadersComplete(); | 560 _httpParser.headersComplete = () => _onHeadersComplete(); |
| 588 _httpParser.dataReceived = (data) => _onDataReceived(data); | 561 _httpParser.dataReceived = (data) => _onDataReceived(data); |
| 589 _httpParser.dataEnd = () => _onDataEnd(); | 562 _httpParser.dataEnd = (close) => _onDataEnd(close); |
| 590 _httpParser.error = (e) => _onError(e); | 563 _httpParser.error = (e) => _onError(e); |
| 591 } | 564 } |
| 592 | 565 |
| 566 void _onConnectionClosed(Exception e) { | |
| 567 if (e != null && onError != null) { | |
| 568 onError(e); | |
| 569 // Propagate the error to the streams. | |
| 570 if (_request != null && _request._streamErrorHandler != null) { | |
| 571 _request._streamErrorHandler(e); | |
| 572 } | |
| 573 if (_response != null && _response._streamErrorHandler != null) { | |
| 574 _response._streamErrorHandler(e); | |
| 575 } | |
| 576 } | |
| 577 | |
| 578 // If currently not processing any request just close the socket. | |
| 579 if (_httpParser.isIdle) { | |
| 580 _socket.close(); | |
| 581 if (onClosed != null && e == null) { | |
| 582 // Don't call onClosed if onError has been called. | |
| 583 onClosed(); | |
| 584 } | |
| 585 return; | |
| 586 } | |
| 587 | |
| 588 // Processing a request. | |
| 589 if (e == null) { | |
| 590 // Indicate connection close to the HTTP parser. | |
| 591 _httpParser.connectionClosed(); | |
| 592 _closing = true; | |
|
Anders Johnsen
2012/04/10 08:18:53
And remove it here, since we mark it in super clas
| |
| 593 } | |
| 594 } | |
| 595 | |
| 593 void _onRequestStart(String method, String uri) { | 596 void _onRequestStart(String method, String uri) { |
| 594 // Create new request and response objects for this request. | 597 // Create new request and response objects for this request. |
| 595 _phase = PHASE_REQUEST; | |
| 596 _request = new _HttpRequest(this); | 598 _request = new _HttpRequest(this); |
| 597 _response = new _HttpResponse(this); | 599 _response = new _HttpResponse(this); |
| 598 _request._onRequestStart(method, uri); | 600 _request._onRequestStart(method, uri); |
| 599 } | 601 } |
| 600 | 602 |
| 601 void _onResponseStart(int statusCode, String reasonPhrase) { | 603 void _onResponseStart(int statusCode, String reasonPhrase) { |
| 602 // TODO(sgjesse): Error handling. | 604 // TODO(sgjesse): Error handling. |
| 603 } | 605 } |
| 604 | 606 |
| 605 void _onHeaderReceived(String name, String value) { | 607 void _onHeaderReceived(String name, String value) { |
| 606 _request._onHeaderReceived(name, value); | 608 _request._onHeaderReceived(name, value); |
| 607 } | 609 } |
| 608 | 610 |
| 609 void _onHeadersComplete() { | 611 void _onHeadersComplete() { |
| 610 _request._onHeadersComplete(); | 612 _request._onHeadersComplete(); |
| 611 _response.keepAlive = _httpParser.keepAlive; | 613 _response.keepAlive = _httpParser.keepAlive; |
| 612 if (requestReceived != null) { | 614 if (onRequestReceived != null) { |
| 613 requestReceived(_request, _response); | 615 onRequestReceived(_request, _response); |
| 614 } | 616 } |
| 615 } | 617 } |
| 616 | 618 |
| 617 void _onDataReceived(List<int> data) { | 619 void _onDataReceived(List<int> data) { |
| 618 _request._onDataReceived(data); | 620 _request._onDataReceived(data); |
| 619 } | 621 } |
| 620 | 622 |
| 621 void _onDataEnd() { | 623 void _onDataEnd(bool close) { |
| 622 // Phase might already have gone to PHASE_IDLE if the response is | 624 if (_request != null) { |
| 623 // sent without waiting for request body. | 625 _request._onDataEnd(); |
| 624 if (_phase == PHASE_REQUEST) { | |
| 625 _phase = PHASE_RESPONSE; | |
| 626 } | 626 } |
| 627 _request._onDataEnd(); | 627 _request = null; |
| 628 } | 628 } |
| 629 | 629 |
| 630 void _propagateError(Exception e) { | 630 void _responseDone() { |
| 631 if (_request != null && _request._streamErrorHandler != null) { | 631 // If the connection is closing then close the output stream to |
| 632 _request._streamErrorHandler(e); | 632 // fully close the socket. |
| 633 if (_closing) { | |
| 634 outputStream.close(); | |
| 633 } | 635 } |
| 634 if (_response != null && _response._streamErrorHandler != null) { | 636 _response = null; |
| 635 _response._streamErrorHandler(e); | |
| 636 } | |
| 637 } | 637 } |
| 638 | 638 |
| 639 HttpServer _server; | 639 HttpServer _server; |
| 640 HttpRequest _request; | 640 HttpRequest _request; |
| 641 HttpResponse _response; | 641 HttpResponse _response; |
| 642 | 642 |
| 643 // Callbacks. | 643 // Callbacks. |
| 644 var requestReceived; | 644 Function onRequestReceived; |
| 645 Function onClosed; | |
| 646 Function onError; | |
| 645 } | 647 } |
| 646 | 648 |
| 647 | 649 |
| 648 // HTTP server waiting for socket connections. The connections are | 650 // HTTP server waiting for socket connections. The connections are |
| 649 // managed by the server and as requests are received the request. | 651 // managed by the server and as requests are received the request. |
| 650 class _HttpServer implements HttpServer { | 652 class _HttpServer implements HttpServer { |
| 651 _HttpServer() : _connections = new Set<_HttpConnection>(); | 653 _HttpServer() : _connections = new Set<_HttpConnection>(); |
| 652 | 654 |
| 653 void listen(String host, int port, [int backlog = 5]) { | 655 void listen(String host, int port, [int backlog = 5]) { |
| 654 listenOn(new ServerSocket(host, port, backlog)); | 656 listenOn(new ServerSocket(host, port, backlog)); |
| 655 _closeServer = true; | 657 _closeServer = true; |
| 656 } | 658 } |
| 657 | 659 |
| 658 void listenOn(ServerSocket serverSocket) { | 660 void listenOn(ServerSocket serverSocket) { |
| 659 void onConnection(Socket socket) { | 661 void onConnection(Socket socket) { |
| 660 // Accept the client connection. | 662 // Accept the client connection. |
| 661 _HttpConnection connection = new _HttpConnection(this); | 663 _HttpConnection connection = new _HttpConnection(this); |
| 662 connection.requestReceived = _onRequest; | 664 connection._connectionEstablished(socket); |
| 663 connection.onDisconnect = () => _connections.remove(connection); | 665 connection.onRequestReceived = _onRequest; |
| 666 connection.onClosed = () => _connections.remove(connection); | |
| 664 connection.onError = (e) { | 667 connection.onError = (e) { |
| 668 _connections.remove(connection); | |
| 665 if (_onError != null) _onError(e); | 669 if (_onError != null) _onError(e); |
| 666 }; | 670 }; |
| 667 connection._connectionEstablished(socket); | 671 connection._connectionEstablished(socket); |
| 668 _connections.add(connection); | 672 _connections.add(connection); |
| 669 } | 673 } |
| 670 serverSocket.onConnection = onConnection; | 674 serverSocket.onConnection = onConnection; |
| 671 _server = serverSocket; | 675 _server = serverSocket; |
| 672 _closeServer = false; | 676 _closeServer = false; |
| 673 } | 677 } |
| 674 | 678 |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 785 bool _streamWriteFrom(List<int> buffer, int offset, int len) { | 789 bool _streamWriteFrom(List<int> buffer, int offset, int len) { |
| 786 return _writeList(buffer, offset, len); | 790 return _writeList(buffer, offset, len); |
| 787 } | 791 } |
| 788 | 792 |
| 789 void _streamClose() { | 793 void _streamClose() { |
| 790 _state = DONE; | 794 _state = DONE; |
| 791 // Stop tracking no pending write events. | 795 // Stop tracking no pending write events. |
| 792 _httpConnection._onNoPendingWrites = null; | 796 _httpConnection._onNoPendingWrites = null; |
| 793 // Ensure that any trailing data is written. | 797 // Ensure that any trailing data is written. |
| 794 _writeDone(); | 798 _writeDone(); |
| 795 // If the connection is closing then close the output stream to | |
| 796 // fully close the socket. | |
| 797 if (_httpConnection._closing) { | |
| 798 _httpConnection._close(); | |
| 799 } | |
| 800 } | 799 } |
| 801 | 800 |
| 802 void _streamSetNoPendingWriteHandler(callback()) { | 801 void _streamSetNoPendingWriteHandler(callback()) { |
| 803 if (_state != DONE) { | 802 if (_state != DONE) { |
| 804 _httpConnection._onNoPendingWrites = callback; | 803 _httpConnection._onNoPendingWrites = callback; |
| 805 } | 804 } |
| 806 } | 805 } |
| 807 | 806 |
| 808 void _streamSetCloseHandler(callback()) { | 807 void _streamSetCloseHandler(callback()) { |
| 809 // TODO(sgjesse): Handle this. | 808 // TODO(sgjesse): Handle this. |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 898 } | 897 } |
| 899 } | 898 } |
| 900 | 899 |
| 901 void _onDataReceived(List<int> data) { | 900 void _onDataReceived(List<int> data) { |
| 902 _buffer.add(data); | 901 _buffer.add(data); |
| 903 if (_inputStream != null) _inputStream._dataReceived(); | 902 if (_inputStream != null) _inputStream._dataReceived(); |
| 904 } | 903 } |
| 905 | 904 |
| 906 void _onDataEnd() { | 905 void _onDataEnd() { |
| 907 if (_inputStream != null) _inputStream._closeReceived(); | 906 if (_inputStream != null) _inputStream._closeReceived(); |
| 907 _connection._responseDone(); | |
| 908 } | 908 } |
| 909 | 909 |
| 910 // Delegate functions for the HttpInputStream implementation. | 910 // Delegate functions for the HttpInputStream implementation. |
| 911 int _streamAvailable() { | 911 int _streamAvailable() { |
| 912 return _buffer.length; | 912 return _buffer.length; |
| 913 } | 913 } |
| 914 | 914 |
| 915 List<int> _streamRead(int bytesToRead) { | 915 List<int> _streamRead(int bytesToRead) { |
| 916 return _buffer.readBytes(bytesToRead); | 916 return _buffer.readBytes(bytesToRead); |
| 917 } | 917 } |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 946 // Register HTTP parser callbacks. | 946 // Register HTTP parser callbacks. |
| 947 _httpParser.requestStart = | 947 _httpParser.requestStart = |
| 948 (method, uri) => _onRequestStart(method, uri); | 948 (method, uri) => _onRequestStart(method, uri); |
| 949 _httpParser.responseStart = | 949 _httpParser.responseStart = |
| 950 (statusCode, reasonPhrase) => | 950 (statusCode, reasonPhrase) => |
| 951 _onResponseStart(statusCode, reasonPhrase); | 951 _onResponseStart(statusCode, reasonPhrase); |
| 952 _httpParser.headerReceived = | 952 _httpParser.headerReceived = |
| 953 (name, value) => _onHeaderReceived(name, value); | 953 (name, value) => _onHeaderReceived(name, value); |
| 954 _httpParser.headersComplete = () => _onHeadersComplete(); | 954 _httpParser.headersComplete = () => _onHeadersComplete(); |
| 955 _httpParser.dataReceived = (data) => _onDataReceived(data); | 955 _httpParser.dataReceived = (data) => _onDataReceived(data); |
| 956 _httpParser.dataEnd = () => _onDataEnd(); | 956 _httpParser.dataEnd = (closed) => _onDataEnd(closed); |
| 957 _httpParser.error = (e) => _onError(e); | 957 _httpParser.error = (e) => _onError(e); |
| 958 // Tell the HTTP parser the method it is expecting a response to. | 958 // Tell the HTTP parser the method it is expecting a response to. |
| 959 _httpParser.responseToMethod = _method; | 959 _httpParser.responseToMethod = _method; |
| 960 | |
| 961 onDisconnect = _onDisconnected; | |
| 962 } | 960 } |
| 963 | 961 |
| 964 void _propagateError(Exception e) { | 962 void _responseDone() { |
| 965 if (_response != null && _response._streamErrorHandler != null) { | 963 if (_closing) { |
| 966 _response._streamErrorHandler(e); | 964 if (_socket != null) { |
| 965 _socket.close(); | |
| 966 } | |
| 967 } else { | |
| 968 _client._returnSocketConnection(_socketConn); | |
| 967 } | 969 } |
| 970 _socket = null; | |
| 971 _socketConn = null; | |
| 968 } | 972 } |
| 969 | 973 |
| 970 HttpClientRequest open(String method, String uri) { | 974 HttpClientRequest open(String method, String uri) { |
| 971 _method = method; | 975 _method = method; |
| 972 _request = new _HttpClientRequest(method, uri, this); | 976 _request = new _HttpClientRequest(method, uri, this); |
| 973 _request.keepAlive = true; | 977 _request.keepAlive = true; |
| 974 _response = new _HttpClientResponse(this); | 978 _response = new _HttpClientResponse(this); |
| 975 return _request; | 979 return _request; |
| 976 } | 980 } |
| 977 | 981 |
| 982 void _onConnectionClosed(Exception e) { | |
| 983 // Socket is closed either due to an error or due to normal socket close. | |
| 984 if (e != null) { | |
| 985 if (_onErrorCallback != null) { | |
| 986 _onErrorCallback(e); | |
| 987 } | |
| 988 } | |
| 989 _closing = true; | |
| 990 if (e != null) { | |
| 991 // Propagate the error to the streams. | |
| 992 if (_response != null && _response._streamErrorHandler != null) { | |
| 993 _response._streamErrorHandler(e); | |
| 994 } | |
| 995 _responseDone(); | |
| 996 } else { | |
| 997 // If there was no socket error the socket was closed | |
| 998 // normally. Indicate closing to the HTTP Parser as there might | |
| 999 // still be an HTTP error. | |
| 1000 _httpParser.connectionClosed(); | |
| 1001 } | |
| 1002 } | |
| 1003 | |
| 978 void _onRequestStart(String method, String uri) { | 1004 void _onRequestStart(String method, String uri) { |
| 979 // TODO(sgjesse): Error handling. | 1005 // TODO(sgjesse): Error handling. |
| 980 } | 1006 } |
| 981 | 1007 |
| 982 void _onResponseStart(int statusCode, String reasonPhrase) { | 1008 void _onResponseStart(int statusCode, String reasonPhrase) { |
| 983 _response._onResponseStart(statusCode, reasonPhrase); | 1009 _response._onResponseStart(statusCode, reasonPhrase); |
| 984 } | 1010 } |
| 985 | 1011 |
| 986 void _onHeaderReceived(String name, String value) { | 1012 void _onHeaderReceived(String name, String value) { |
| 987 _response._onHeaderReceived(name, value); | 1013 _response._onHeaderReceived(name, value); |
| 988 } | 1014 } |
| 989 | 1015 |
| 990 void _onHeadersComplete() { | 1016 void _onHeadersComplete() { |
| 991 _response._onHeadersComplete(); | 1017 _response._onHeadersComplete(); |
| 992 } | 1018 } |
| 993 | 1019 |
| 994 void _onDataReceived(List<int> data) { | 1020 void _onDataReceived(List<int> data) { |
| 995 _response._onDataReceived(data); | 1021 _response._onDataReceived(data); |
| 996 } | 1022 } |
| 997 | 1023 |
| 998 void _onDataEnd() { | 1024 void _onDataEnd(bool close) { |
| 999 onDisconnect = null; | 1025 if (close) _closing = true; |
| 1000 if (_response.headers["connection"] == "close") { | |
| 1001 _socket.close(); | |
| 1002 } else { | |
| 1003 _client._returnSocketConnection(_socketConn); | |
| 1004 } | |
| 1005 _socket = null; | |
| 1006 _socketConn = null; | |
| 1007 _response._onDataEnd(); | 1026 _response._onDataEnd(); |
| 1008 } | 1027 } |
| 1009 | 1028 |
| 1010 void set onRequest(void handler(HttpClientRequest request)) { | 1029 void set onRequest(void handler(HttpClientRequest request)) { |
| 1011 _onRequest = handler; | 1030 _onRequest = handler; |
| 1012 } | 1031 } |
| 1013 | 1032 |
| 1014 void set onResponse(void handler(HttpClientResponse response)) { | 1033 void set onResponse(void handler(HttpClientResponse response)) { |
| 1015 _onResponse = handler; | 1034 _onResponse = handler; |
| 1016 } | 1035 } |
| 1017 | 1036 |
| 1018 void _onDisconnected() { | 1037 void set onError(void callback(Exception e)) { |
| 1019 if (_onErrorCallback !== null) { | 1038 _onErrorCallback = callback; |
| 1020 _onErrorCallback(new HttpException( | |
| 1021 "Client disconnected before response was received.")); | |
| 1022 } | |
| 1023 } | 1039 } |
| 1024 | 1040 |
| 1025 Function _onRequest; | 1041 Function _onRequest; |
| 1026 Function _onResponse; | 1042 Function _onResponse; |
| 1043 Function _onErrorCallback; | |
| 1027 | 1044 |
| 1028 _HttpClient _client; | 1045 _HttpClient _client; |
| 1029 _SocketConnection _socketConn; | 1046 _SocketConnection _socketConn; |
| 1030 HttpClientRequest _request; | 1047 HttpClientRequest _request; |
| 1031 HttpClientResponse _response; | 1048 HttpClientResponse _response; |
| 1032 String _method; | 1049 String _method; |
| 1033 | 1050 |
| 1034 // Callbacks. | 1051 // Callbacks. |
| 1035 var requestReceived; | 1052 var requestReceived; |
| 1036 } | 1053 } |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1227 sockets.addFirst(socketConn); | 1244 sockets.addFirst(socketConn); |
| 1228 socketConn._markReturned(); | 1245 socketConn._markReturned(); |
| 1229 } | 1246 } |
| 1230 | 1247 |
| 1231 Function _onOpen; | 1248 Function _onOpen; |
| 1232 Map<String, Queue<_SocketConnection>> _openSockets; | 1249 Map<String, Queue<_SocketConnection>> _openSockets; |
| 1233 Set<_SocketConnection> _activeSockets; | 1250 Set<_SocketConnection> _activeSockets; |
| 1234 Timer _evictionTimer; | 1251 Timer _evictionTimer; |
| 1235 bool _shutdown; // Has this HTTP client been shutdown? | 1252 bool _shutdown; // Has this HTTP client been shutdown? |
| 1236 } | 1253 } |
| OLD | NEW |