| 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 // Global constants. | 5 // Global constants. |
| 6 class _Const { | 6 class _Const { |
| 7 // Bytes for "HTTP". | 7 // Bytes for "HTTP". |
| 8 static final HTTP = const [72, 84, 84, 80]; | 8 static final HTTP = const [72, 84, 84, 80]; |
| 9 // Bytes for "HTTP/1.". | 9 // Bytes for "HTTP/1.". |
| 10 static final HTTP1DOT = const [72, 84, 84, 80, 47, 49, 46]; | 10 static final HTTP1DOT = const [72, 84, 84, 80, 47, 49, 46]; |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 138 int writeList(List<int> buffer, int offset, int count) { | 138 int writeList(List<int> buffer, int offset, int count) { |
| 139 int index = offset; | 139 int index = offset; |
| 140 int lastIndex = offset + count; | 140 int lastIndex = offset + count; |
| 141 try { | 141 try { |
| 142 if (_state == _State.CLOSED) { | 142 if (_state == _State.CLOSED) { |
| 143 throw new HttpParserException("Data on closed connection"); | 143 throw new HttpParserException("Data on closed connection"); |
| 144 } | 144 } |
| 145 if (_state == _State.UPGRADED) { | 145 if (_state == _State.UPGRADED) { |
| 146 throw new HttpParserException("Data on upgraded connection"); | 146 throw new HttpParserException("Data on upgraded connection"); |
| 147 } | 147 } |
| 148 if (_state == _State.FAILURE) { |
| 149 throw new HttpParserException("Data on failed connection"); |
| 150 } |
| 148 while ((index < lastIndex) && _state != _State.FAILURE && _state != _State
.UPGRADED) { | 151 while ((index < lastIndex) && _state != _State.FAILURE && _state != _State
.UPGRADED) { |
| 149 int byte = buffer[index]; | 152 int byte = buffer[index]; |
| 150 switch (_state) { | 153 switch (_state) { |
| 151 case _State.START: | 154 case _State.START: |
| 152 if (byte == _Const.HTTP[0]) { | 155 if (byte == _Const.HTTP[0]) { |
| 153 // Start parsing method or HTTP version. | 156 // Start parsing method or HTTP version. |
| 154 _httpVersionIndex = 1; | 157 _httpVersionIndex = 1; |
| 155 _state = _State.METHOD_OR_RESPONSE_HTTP_VERSION; | 158 _state = _State.METHOD_OR_RESPONSE_HTTP_VERSION; |
| 156 } else { | 159 } else { |
| 157 // Start parsing method. | 160 // Start parsing method. |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 361 _expect(byte, _CharCode.LF); | 364 _expect(byte, _CharCode.LF); |
| 362 _state = _State.HEADER_VALUE_FOLD_OR_END; | 365 _state = _State.HEADER_VALUE_FOLD_OR_END; |
| 363 break; | 366 break; |
| 364 | 367 |
| 365 case _State.HEADER_VALUE_FOLD_OR_END: | 368 case _State.HEADER_VALUE_FOLD_OR_END: |
| 366 if (byte == _CharCode.SP || byte == _CharCode.HT) { | 369 if (byte == _CharCode.SP || byte == _CharCode.HT) { |
| 367 _state = _State.HEADER_VALUE_START; | 370 _state = _State.HEADER_VALUE_START; |
| 368 } else { | 371 } else { |
| 369 String headerField = _headerField.toString(); | 372 String headerField = _headerField.toString(); |
| 370 String headerValue =_headerValue.toString(); | 373 String headerValue =_headerValue.toString(); |
| 371 // Ignore the Content-Length header if Transfer-Encoding | 374 bool reportHeader = true; |
| 372 // is chunked (RFC 2616 section 4.4) | |
| 373 if (headerField == "content-length" && !_chunked) { | 375 if (headerField == "content-length" && !_chunked) { |
| 376 // Ignore the Content-Length header if Transfer-Encoding |
| 377 // is chunked (RFC 2616 section 4.4) |
| 374 _contentLength = Math.parseInt(headerValue); | 378 _contentLength = Math.parseInt(headerValue); |
| 375 } else if (headerField == "connection") { | 379 } else if (headerField == "connection") { |
| 376 List<String> tokens = _tokenizeFieldValue(headerValue); | 380 List<String> tokens = _tokenizeFieldValue(headerValue); |
| 377 for (int i = 0; i < tokens.length; i++) { | 381 for (int i = 0; i < tokens.length; i++) { |
| 378 String token = tokens[i].toLowerCase(); | 382 String token = tokens[i].toLowerCase(); |
| 379 if (token == "keep-alive") { | 383 if (token == "keep-alive") { |
| 380 _persistentConnection = true; | 384 _persistentConnection = true; |
| 381 } else if (token == "close") { | 385 } else if (token == "close") { |
| 382 _persistentConnection = false; | 386 _persistentConnection = false; |
| 383 } else if (token == "upgrade") { | 387 } else if (token == "upgrade") { |
| 384 _connectionUpgrade = true; | 388 _connectionUpgrade = true; |
| 385 } | 389 } |
| 390 if (headerReceived != null) { |
| 391 headerReceived(headerField, token); |
| 392 } |
| 386 } | 393 } |
| 394 reportHeader = false; |
| 387 } else if (headerField == "transfer-encoding" && | 395 } else if (headerField == "transfer-encoding" && |
| 388 headerValue.toLowerCase() == "chunked") { | 396 headerValue.toLowerCase() == "chunked") { |
| 397 // Ignore the Content-Length header if Transfer-Encoding |
| 398 // is chunked (RFC 2616 section 4.4) |
| 389 _chunked = true; | 399 _chunked = true; |
| 390 _contentLength = -1; | 400 _contentLength = -1; |
| 391 } | 401 } |
| 392 if (headerReceived != null) { | 402 if (reportHeader && headerReceived != null) { |
| 393 headerReceived(headerField, headerValue); | 403 headerReceived(headerField, headerValue); |
| 394 } | 404 } |
| 395 _headerField.clear(); | 405 _headerField.clear(); |
| 396 _headerValue.clear(); | 406 _headerValue.clear(); |
| 397 | 407 |
| 398 if (byte == _CharCode.CR) { | 408 if (byte == _CharCode.CR) { |
| 399 _state = _State.HEADER_ENDING; | 409 _state = _State.HEADER_ENDING; |
| 400 } else { | 410 } else { |
| 401 // Start of new header field. | 411 // Start of new header field. |
| 402 _headerField.addCharCode(_toLowerCase(byte)); | 412 _headerField.addCharCode(_toLowerCase(byte)); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 476 _state = _State.CHUNKED_BODY_DONE_LF; | 486 _state = _State.CHUNKED_BODY_DONE_LF; |
| 477 break; | 487 break; |
| 478 | 488 |
| 479 case _State.CHUNKED_BODY_DONE_LF: | 489 case _State.CHUNKED_BODY_DONE_LF: |
| 480 _expect(byte, _CharCode.LF); | 490 _expect(byte, _CharCode.LF); |
| 481 _bodyEnd(); | 491 _bodyEnd(); |
| 482 _reset(); | 492 _reset(); |
| 483 break; | 493 break; |
| 484 | 494 |
| 485 case _State.BODY: | 495 case _State.BODY: |
| 486 // The body is not handled one byte at the time but in blocks. | 496 // The body is not handled one byte at a time but in blocks. |
| 487 int dataAvailable = lastIndex - index; | 497 int dataAvailable = lastIndex - index; |
| 488 ByteArray data; | 498 ByteArray data; |
| 489 if (_remainingContent == null || | 499 if (_remainingContent == null || |
| 490 dataAvailable <= _remainingContent) { | 500 dataAvailable <= _remainingContent) { |
| 491 data = new ByteArray(dataAvailable); | 501 data = new ByteArray(dataAvailable); |
| 492 data.setRange(0, dataAvailable, buffer, index); | 502 data.setRange(0, dataAvailable, buffer, index); |
| 493 } else { | 503 } else { |
| 494 data = new ByteArray(_remainingContent); | 504 data = new ByteArray(_remainingContent); |
| 495 data.setRange(0, _remainingContent, buffer, index); | 505 data.setRange(0, _remainingContent, buffer, index); |
| 496 } | 506 } |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 694 Function dataEnd; | 704 Function dataEnd; |
| 695 Function error; | 705 Function error; |
| 696 } | 706 } |
| 697 | 707 |
| 698 | 708 |
| 699 class HttpParserException implements Exception { | 709 class HttpParserException implements Exception { |
| 700 const HttpParserException([String this.message = ""]); | 710 const HttpParserException([String this.message = ""]); |
| 701 String toString() => "HttpParserException: $message"; | 711 String toString() => "HttpParserException: $message"; |
| 702 final String message; | 712 final String message; |
| 703 } | 713 } |
| OLD | NEW |