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 // Global constants. | 5 // Global constants. |
| 6 class _Const { | 6 class _Const { |
| 7 // Bytes for "HTTP". | |
| 8 static final HTTP = const [72, 84, 84, 80]; | |
| 9 // Bytes for "HTTP/1.". | |
| 10 static final HTTP1DOT = const [72, 84, 84, 80, 47, 49, 46]; | |
| 7 // Bytes for "HTTP/1.0". | 11 // Bytes for "HTTP/1.0". |
| 8 static final HTTP10 = const [72, 84, 84, 80, 47, 49, 46, 48]; | 12 static final HTTP10 = const [72, 84, 84, 80, 47, 49, 46, 48]; |
| 9 // Bytes for "HTTP/1.1". | 13 // Bytes for "HTTP/1.1". |
| 10 static final HTTP11 = const [72, 84, 84, 80, 47, 49, 46, 49]; | 14 static final HTTP11 = const [72, 84, 84, 80, 47, 49, 46, 49]; |
| 11 | 15 |
| 12 static final END_CHUNKED = const [0x30, 13, 10, 13, 10]; | 16 static final END_CHUNKED = const [0x30, 13, 10, 13, 10]; |
| 13 | 17 |
| 14 // Bytes for '()<>@,;:\\"/[]?={} \t'. | 18 // Bytes for '()<>@,;:\\"/[]?={} \t'. |
| 15 static final SEPARATORS = const [40, 41, 60, 62, 64, 44, 59, 58, 92, 34, 47, | 19 static final SEPARATORS = const [40, 41, 60, 62, 64, 44, 59, 58, 92, 34, 47, |
| 16 91, 93, 63, 61, 123, 125, 32, 9]; | 20 91, 93, 63, 61, 123, 125, 32, 9]; |
| 17 | 21 |
| 18 // Bytes for '()<>@,;:\\"/[]?={} \t\r\n'. | 22 // Bytes for '()<>@,;:\\"/[]?={} \t\r\n'. |
| 19 static final SEPARATORS_AND_CR_LF = const [40, 41, 60, 62, 64, 44, 59, 58, 92, | 23 static final SEPARATORS_AND_CR_LF = const [40, 41, 60, 62, 64, 44, 59, 58, 92, |
| 20 34, 47, 91, 93, 63, 61, 123, 125, | 24 34, 47, 91, 93, 63, 61, 123, 125, |
| 21 32, 9, 13, 10]; | 25 32, 9, 13, 10]; |
| 22 } | 26 } |
| 23 | 27 |
| 24 | 28 |
| 25 // Frequently used character codes. | 29 // Frequently used character codes. |
| 26 class _CharCode { | 30 class _CharCode { |
| 27 static final int HT = 9; | 31 static final int HT = 9; |
| 28 static final int LF = 10; | 32 static final int LF = 10; |
| 29 static final int CR = 13; | 33 static final int CR = 13; |
| 30 static final int SP = 32; | 34 static final int SP = 32; |
| 35 static final int SLASH = 47; | |
| 36 static final int ZERO = 48; | |
| 37 static final int ONE = 49; | |
| 31 static final int COLON = 58; | 38 static final int COLON = 58; |
| 32 static final int SEMI_COLON = 59; | 39 static final int SEMI_COLON = 59; |
| 33 } | 40 } |
| 34 | 41 |
| 35 | 42 |
| 36 // States of the HTTP parser state machine. | 43 // States of the HTTP parser state machine. |
| 37 class _State { | 44 class _State { |
| 38 static final int START = 0; | 45 static final int START = 0; |
| 39 static final int METHOD_OR_HTTP_VERSION = 1; | 46 static final int METHOD_OR_RESPONSE_HTTP_VERSION = 1; |
| 40 static final int REQUEST_LINE_METHOD = 2; | 47 static final int RESPONSE_HTTP_VERSION = 2; |
| 41 static final int REQUEST_LINE_URI = 3; | 48 static final int REQUEST_LINE_METHOD = 3; |
| 42 static final int REQUEST_LINE_HTTP_VERSION = 4; | 49 static final int REQUEST_LINE_URI = 4; |
| 43 static final int REQUEST_LINE_ENDING = 5; | 50 static final int REQUEST_LINE_HTTP_VERSION = 5; |
| 44 static final int RESPONSE_LINE_STATUS_CODE = 6; | 51 static final int REQUEST_LINE_ENDING = 6; |
| 45 static final int RESPONSE_LINE_REASON_PHRASE = 7; | 52 static final int RESPONSE_LINE_STATUS_CODE = 7; |
| 46 static final int RESPONSE_LINE_ENDING = 8; | 53 static final int RESPONSE_LINE_REASON_PHRASE = 8; |
| 47 static final int HEADER_START = 9; | 54 static final int RESPONSE_LINE_ENDING = 9; |
| 48 static final int HEADER_FIELD = 10; | 55 static final int HEADER_START = 10; |
| 49 static final int HEADER_VALUE_START = 11; | 56 static final int HEADER_FIELD = 11; |
| 50 static final int HEADER_VALUE = 12; | 57 static final int HEADER_VALUE_START = 12; |
| 51 static final int HEADER_VALUE_FOLDING_OR_ENDING = 13; | 58 static final int HEADER_VALUE = 13; |
| 52 static final int HEADER_VALUE_FOLD_OR_END = 14; | 59 static final int HEADER_VALUE_FOLDING_OR_ENDING = 14; |
| 53 static final int HEADER_ENDING = 15; | 60 static final int HEADER_VALUE_FOLD_OR_END = 15; |
| 61 static final int HEADER_ENDING = 16; | |
| 54 | 62 |
| 55 static final int CHUNK_SIZE_STARTING_CR = 16; | 63 static final int CHUNK_SIZE_STARTING_CR = 17; |
| 56 static final int CHUNK_SIZE_STARTING_LF = 17; | 64 static final int CHUNK_SIZE_STARTING_LF = 18; |
| 57 static final int CHUNK_SIZE = 18; | 65 static final int CHUNK_SIZE = 19; |
| 58 static final int CHUNK_SIZE_EXTENSION = 19; | 66 static final int CHUNK_SIZE_EXTENSION = 20; |
| 59 static final int CHUNK_SIZE_ENDING = 20; | 67 static final int CHUNK_SIZE_ENDING = 21; |
| 60 static final int CHUNKED_BODY_DONE_CR = 21; | 68 static final int CHUNKED_BODY_DONE_CR = 22; |
| 61 static final int CHUNKED_BODY_DONE_LF = 22; | 69 static final int CHUNKED_BODY_DONE_LF = 23; |
| 62 static final int BODY = 23; | 70 static final int BODY = 24; |
| 63 static final int CLOSED = 24; | 71 static final int CLOSED = 25; |
| 64 static final int UPGRADED = 25; | 72 static final int UPGRADED = 26; |
| 65 static final int FAILURE = 26; | 73 static final int FAILURE = 27; |
| 66 | 74 |
| 67 static final int FIRST_BODY_STATE = CHUNK_SIZE_STARTING_CR; | 75 static final int FIRST_BODY_STATE = CHUNK_SIZE_STARTING_CR; |
| 68 } | 76 } |
| 69 | 77 |
| 78 // HTTP version of the request or response being parsed. | |
| 79 class _HttpVersion { | |
| 80 static final int UNDETERMINED = 0; | |
| 81 static final int HTTP10 = 1; | |
| 82 static final int HTTP11 = 2; | |
| 83 } | |
| 70 | 84 |
| 71 // States of the HTTP parser state machine. | 85 // States of the HTTP parser state machine. |
| 72 class _MessageType { | 86 class _MessageType { |
| 73 static final int UNDETERMINED = 0; | 87 static final int UNDETERMINED = 0; |
| 74 static final int REQUEST = 1; | 88 static final int REQUEST = 1; |
| 75 static final int RESPONSE = 0; | 89 static final int RESPONSE = 0; |
| 76 } | 90 } |
| 77 | 91 |
| 78 | 92 |
| 79 /** | 93 /** |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 127 if (_state == _State.CLOSED) { | 141 if (_state == _State.CLOSED) { |
| 128 throw new HttpParserException("Data on closed connection"); | 142 throw new HttpParserException("Data on closed connection"); |
| 129 } | 143 } |
| 130 if (_state == _State.UPGRADED) { | 144 if (_state == _State.UPGRADED) { |
| 131 throw new HttpParserException("Data on upgraded connection"); | 145 throw new HttpParserException("Data on upgraded connection"); |
| 132 } | 146 } |
| 133 while ((index < lastIndex) && _state != _State.FAILURE && _state != _State .UPGRADED) { | 147 while ((index < lastIndex) && _state != _State.FAILURE && _state != _State .UPGRADED) { |
| 134 int byte = buffer[index]; | 148 int byte = buffer[index]; |
| 135 switch (_state) { | 149 switch (_state) { |
| 136 case _State.START: | 150 case _State.START: |
| 137 if (byte == _Const.HTTP11[0]) { | 151 if (byte == _Const.HTTP[0]) { |
| 138 // Start parsing HTTP method. | 152 // Start parsing method or HTTP version. |
| 139 _httpVersionIndex = 1; | 153 _httpVersionIndex = 1; |
| 140 _state = _State.METHOD_OR_HTTP_VERSION; | 154 _state = _State.METHOD_OR_RESPONSE_HTTP_VERSION; |
| 141 } else { | 155 } else { |
| 142 // Start parsing method. | 156 // Start parsing method. |
| 143 if (_Const.SEPARATORS_AND_CR_LF.indexOf(byte) != -1) { | 157 if (!_isTokenChar(byte)) { |
| 144 throw new HttpParserException("Invalid request method"); | 158 throw new HttpParserException("Invalid request method"); |
| 145 } | 159 } |
| 146 _method_or_status_code.addCharCode(byte); | 160 _method_or_status_code.addCharCode(byte); |
| 147 _state = _State.REQUEST_LINE_METHOD; | 161 _state = _State.REQUEST_LINE_METHOD; |
| 148 } | 162 } |
| 149 break; | 163 break; |
| 150 | 164 |
| 151 case _State.METHOD_OR_HTTP_VERSION: | 165 case _State.METHOD_OR_RESPONSE_HTTP_VERSION: |
| 152 if (_httpVersionIndex < _Const.HTTP11.length && | 166 if (_httpVersionIndex < _Const.HTTP.length && |
| 153 byte == _Const.HTTP11[_httpVersionIndex]) { | 167 byte == _Const.HTTP[_httpVersionIndex]) { |
| 154 // Continue parsing HTTP version. | 168 // Continue parsing HTTP version. |
| 155 _httpVersionIndex++; | 169 _httpVersionIndex++; |
| 156 } else if (_httpVersionIndex == _Const.HTTP11.length && | 170 } else if (_httpVersionIndex == _Const.HTTP.length && |
| 157 byte == _CharCode.SP) { | 171 byte == _CharCode.SLASH) { |
| 172 // HTTP/ parsed. As method is a token this cannot be a method anym ore. | |
| 173 _httpVersionIndex++; | |
| 174 _state = _State.RESPONSE_HTTP_VERSION; | |
| 175 } else { | |
| 176 // Did not parse HTTP version. Expect method instead. | |
| 177 for (int i = 0; i < _httpVersionIndex; i++) { | |
| 178 _method_or_status_code.addCharCode(_Const.HTTP[i]); | |
| 179 } | |
| 180 //_method_or_status_code.addCharCode(byte); | |
| 181 _httpVersion = _HttpVersion.UNDETERMINED; | |
| 182 _state = _State.REQUEST_LINE_URI; | |
| 183 } | |
| 184 break; | |
| 185 | |
| 186 case _State.RESPONSE_HTTP_VERSION: | |
| 187 if (_httpVersionIndex < _Const.HTTP1DOT.length) { | |
| 188 // Continue parsing HTTP version. | |
| 189 _expect(byte, _Const.HTTP1DOT[_httpVersionIndex]); | |
| 190 _httpVersionIndex++; | |
| 191 } else if (_httpVersionIndex == _Const.HTTP1DOT.length && | |
| 192 byte == _CharCode.ONE) { | |
| 193 // HTTP/1.1 parsed. | |
| 194 _httpVersion = _HttpVersion.HTTP11; | |
| 195 _persistentConnection = true; | |
| 196 _httpVersionIndex++; | |
| 197 } else if (_httpVersionIndex == _Const.HTTP1DOT.length && | |
| 198 byte == _CharCode.ZERO) { | |
| 199 // HTTP/1.0 parsed. | |
| 200 _httpVersion = _HttpVersion.HTTP10; | |
| 201 _persistentConnection = false; | |
| 202 _httpVersionIndex++; | |
| 203 } else if (_httpVersionIndex == _Const.HTTP1DOT.length + 1) { | |
| 204 _expect(byte, _CharCode.SP); | |
| 158 // HTTP version parsed. | 205 // HTTP version parsed. |
| 159 _state = _State.RESPONSE_LINE_STATUS_CODE; | 206 _state = _State.RESPONSE_LINE_STATUS_CODE; |
| 160 } else { | 207 } else { |
| 161 // Did not parse HTTP version. Expect method instead. | 208 throw new HttpParserException("Invalid response line"); |
| 162 for (int i = 0; i < _httpVersionIndex; i++) { | |
| 163 _method_or_status_code.addCharCode(_Const.HTTP11[i]); | |
| 164 } | |
| 165 _state = _State.REQUEST_LINE_URI; | |
| 166 } | 209 } |
| 167 break; | 210 break; |
| 168 | 211 |
| 169 case _State.REQUEST_LINE_METHOD: | 212 case _State.REQUEST_LINE_METHOD: |
| 170 if (byte == _CharCode.SP) { | 213 if (byte == _CharCode.SP) { |
| 171 _state = _State.REQUEST_LINE_URI; | 214 _state = _State.REQUEST_LINE_URI; |
| 172 } else { | 215 } else { |
| 173 if (_Const.SEPARATORS_AND_CR_LF.indexOf(byte) != -1) { | 216 if (_Const.SEPARATORS_AND_CR_LF.indexOf(byte) != -1) { |
| 174 throw new HttpParserException("Invalid request method"); | 217 throw new HttpParserException("Invalid request method"); |
| 175 } | 218 } |
| 176 _method_or_status_code.addCharCode(byte); | 219 _method_or_status_code.addCharCode(byte); |
| 177 } | 220 } |
| 178 break; | 221 break; |
| 179 | 222 |
| 180 case _State.REQUEST_LINE_URI: | 223 case _State.REQUEST_LINE_URI: |
| 181 if (byte == _CharCode.SP) { | 224 if (byte == _CharCode.SP) { |
| 182 _state = _State.REQUEST_LINE_HTTP_VERSION; | 225 _state = _State.REQUEST_LINE_HTTP_VERSION; |
| 183 _httpVersionIndex = 0; | 226 _httpVersionIndex = 0; |
| 184 } else { | 227 } else { |
| 185 if (byte == _CharCode.CR || byte == _CharCode.LF) { | 228 if (byte == _CharCode.CR || byte == _CharCode.LF) { |
| 186 throw new HttpParserException("Invalid request URI"); | 229 throw new HttpParserException("Invalid request URI"); |
| 187 } | 230 } |
| 188 _uri_or_reason_phrase.addCharCode(byte); | 231 _uri_or_reason_phrase.addCharCode(byte); |
| 189 } | 232 } |
| 190 break; | 233 break; |
| 191 | 234 |
| 192 case _State.REQUEST_LINE_HTTP_VERSION: | 235 case _State.REQUEST_LINE_HTTP_VERSION: |
| 193 if (_httpVersionIndex < _Const.HTTP11.length) { | 236 if (_httpVersionIndex < _Const.HTTP1DOT.length) { |
| 194 _expect(byte, _Const.HTTP11[_httpVersionIndex]); | 237 _expect(byte, _Const.HTTP11[_httpVersionIndex]); |
| 195 _httpVersionIndex++; | 238 _httpVersionIndex++; |
| 239 } else if (_httpVersionIndex == _Const.HTTP1DOT.length) { | |
| 240 if (byte == _CharCode.ONE) { | |
| 241 // HTTP/1.1 parsed. | |
| 242 _httpVersion = _HttpVersion.HTTP11; | |
| 243 _persistentConnection = true; | |
| 244 _httpVersionIndex++; | |
| 245 } else if (byte == _CharCode.ZERO) { | |
| 246 // HTTP/1.0 parsed. | |
| 247 _httpVersion = _HttpVersion.HTTP10; | |
| 248 _persistentConnection = false; | |
| 249 _httpVersionIndex++; | |
| 250 } else { | |
| 251 throw new HttpParserException("Invalid response line"); | |
| 252 } | |
| 196 } else { | 253 } else { |
| 197 _expect(byte, _CharCode.CR); | 254 _expect(byte, _CharCode.CR); |
| 198 _state = _State.REQUEST_LINE_ENDING; | 255 _state = _State.REQUEST_LINE_ENDING; |
| 199 } | 256 } |
| 200 break; | 257 break; |
| 201 | 258 |
| 202 case _State.REQUEST_LINE_ENDING: | 259 case _State.REQUEST_LINE_ENDING: |
| 203 _expect(byte, _CharCode.LF); | 260 _expect(byte, _CharCode.LF); |
| 204 _messageType = _MessageType.REQUEST; | 261 _messageType = _MessageType.REQUEST; |
| 205 if (requestStart != null) { | 262 if (requestStart != null) { |
| 206 requestStart(_method_or_status_code.toString(), | 263 requestStart(_method_or_status_code.toString(), |
| 207 _uri_or_reason_phrase.toString()); | 264 _uri_or_reason_phrase.toString(), |
| 265 version); | |
| 208 } | 266 } |
| 209 _method_or_status_code.clear(); | 267 _method_or_status_code.clear(); |
| 210 _uri_or_reason_phrase.clear(); | 268 _uri_or_reason_phrase.clear(); |
| 211 _state = _State.HEADER_START; | 269 _state = _State.HEADER_START; |
| 212 break; | 270 break; |
| 213 | 271 |
| 214 case _State.RESPONSE_LINE_STATUS_CODE: | 272 case _State.RESPONSE_LINE_STATUS_CODE: |
| 215 if (byte == _CharCode.SP) { | 273 if (byte == _CharCode.SP) { |
| 216 if (_method_or_status_code.length != 3) { | 274 if (_method_or_status_code.length != 3) { |
| 217 throw new HttpParserException("Invalid response status code"); | 275 throw new HttpParserException("Invalid response status code"); |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 245 _messageType == _MessageType.RESPONSE; | 303 _messageType == _MessageType.RESPONSE; |
| 246 int statusCode = Math.parseInt(_method_or_status_code.toString()); | 304 int statusCode = Math.parseInt(_method_or_status_code.toString()); |
| 247 if (statusCode < 100 || statusCode > 599) { | 305 if (statusCode < 100 || statusCode > 599) { |
| 248 throw new HttpParserException("Invalid response status code"); | 306 throw new HttpParserException("Invalid response status code"); |
| 249 } else { | 307 } else { |
| 250 // Check whether this response will never have a body. | 308 // Check whether this response will never have a body. |
| 251 _noMessageBody = | 309 _noMessageBody = |
| 252 statusCode <= 199 || statusCode == 204 || statusCode == 304; | 310 statusCode <= 199 || statusCode == 204 || statusCode == 304; |
| 253 } | 311 } |
| 254 if (responseStart != null) { | 312 if (responseStart != null) { |
| 255 responseStart(statusCode, _uri_or_reason_phrase.toString()); | 313 responseStart(statusCode, _uri_or_reason_phrase.toString(), versio n); |
| 256 } | 314 } |
| 257 _method_or_status_code.clear(); | 315 _method_or_status_code.clear(); |
| 258 _uri_or_reason_phrase.clear(); | 316 _uri_or_reason_phrase.clear(); |
| 259 _state = _State.HEADER_START; | 317 _state = _State.HEADER_START; |
| 260 break; | 318 break; |
| 261 | 319 |
| 262 case _State.HEADER_START: | 320 case _State.HEADER_START: |
| 263 if (byte == _CharCode.CR) { | 321 if (byte == _CharCode.CR) { |
| 264 _state = _State.HEADER_ENDING; | 322 _state = _State.HEADER_ENDING; |
| 265 } else { | 323 } else { |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 311 String headerValue =_headerValue.toString(); | 369 String headerValue =_headerValue.toString(); |
| 312 // Ignore the Content-Length header if Transfer-Encoding | 370 // Ignore the Content-Length header if Transfer-Encoding |
| 313 // is chunked (RFC 2616 section 4.4) | 371 // is chunked (RFC 2616 section 4.4) |
| 314 if (headerField == "content-length" && !_chunked) { | 372 if (headerField == "content-length" && !_chunked) { |
| 315 _contentLength = Math.parseInt(headerValue); | 373 _contentLength = Math.parseInt(headerValue); |
| 316 } else if (headerField == "connection") { | 374 } else if (headerField == "connection") { |
| 317 List<String> tokens = _tokenizeFieldValue(headerValue); | 375 List<String> tokens = _tokenizeFieldValue(headerValue); |
| 318 for (int i = 0; i < tokens.length; i++) { | 376 for (int i = 0; i < tokens.length; i++) { |
| 319 String token = tokens[i].toLowerCase(); | 377 String token = tokens[i].toLowerCase(); |
| 320 if (token == "keep-alive") { | 378 if (token == "keep-alive") { |
| 321 _keepAlive = true; | 379 _persistentConnection = true; |
| 322 } else if (token == "close") { | 380 } else if (token == "close") { |
| 323 _connectionClose = true; | 381 _persistentConnection = false; |
| 324 } else if (token == "upgrade") { | 382 } else if (token == "upgrade") { |
| 325 _connectionUpgrade = true; | 383 _connectionUpgrade = true; |
| 326 } | 384 } |
| 327 } | 385 } |
| 328 } else if (headerField == "transfer-encoding" && | 386 } else if (headerField == "transfer-encoding" && |
|
Anders Johnsen
2012/04/13 09:02:38
toLowerCase here as well. Actually, maybe we shoul
Søren Gjesse
2012/04/13 10:58:31
This is not required. When the header name is pars
| |
| 329 headerValue == "chunked") { | 387 headerValue.toLowerCase() == "chunked") { |
| 330 _chunked = true; | 388 _chunked = true; |
| 331 _contentLength = -1; | 389 _contentLength = -1; |
| 332 } | 390 } |
| 333 if (headerReceived != null) { | 391 if (headerReceived != null) { |
| 334 headerReceived(headerField, headerValue); | 392 headerReceived(headerField, headerValue); |
| 335 } | 393 } |
| 336 _headerField.clear(); | 394 _headerField.clear(); |
| 337 _headerValue.clear(); | 395 _headerValue.clear(); |
| 338 | 396 |
| 339 if (byte == _CharCode.CR) { | 397 if (byte == _CharCode.CR) { |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 509 var e = new HttpParserException( | 567 var e = new HttpParserException( |
| 510 "Connection closed before full body was received"); | 568 "Connection closed before full body was received"); |
| 511 if (error != null) { | 569 if (error != null) { |
| 512 error(e); | 570 error(e); |
| 513 return; | 571 return; |
| 514 } | 572 } |
| 515 throw e; | 573 throw e; |
| 516 } | 574 } |
| 517 } | 575 } |
| 518 | 576 |
| 577 String get version() { | |
| 578 switch (_httpVersion) { | |
| 579 case _HttpVersion.HTTP10: | |
| 580 return "1.0"; | |
| 581 break; | |
| 582 case _HttpVersion.HTTP11: | |
| 583 return "1.1"; | |
| 584 break; | |
| 585 } | |
| 586 return null; | |
| 587 } | |
| 588 | |
| 519 int get messageType() => _messageType; | 589 int get messageType() => _messageType; |
| 520 int get contentLength() => _contentLength; | 590 int get contentLength() => _contentLength; |
| 521 bool get keepAlive() => _keepAlive; | |
| 522 bool get upgrade() => _connectionUpgrade && _state == _State.UPGRADED; | 591 bool get upgrade() => _connectionUpgrade && _state == _State.UPGRADED; |
| 592 bool get persistentConnection() => _persistentConnection; | |
| 523 | 593 |
| 524 void set responseToMethod(String method) => _responseToMethod = method; | 594 void set responseToMethod(String method) => _responseToMethod = method; |
| 525 | 595 |
| 526 bool get isIdle() => _state == _State.START; | 596 bool get isIdle() => _state == _State.START; |
| 527 | 597 |
| 528 void _bodyEnd() { | 598 void _bodyEnd() { |
| 529 if (dataEnd != null) { | 599 if (dataEnd != null) { |
| 530 dataEnd(_messageType == _MessageType.RESPONSE && _connectionClose); | 600 dataEnd(_messageType == _MessageType.RESPONSE && !_persistentConnection); |
| 531 } | 601 } |
| 532 } | 602 } |
| 533 | 603 |
| 534 _reset() { | 604 _reset() { |
| 535 _state = _State.START; | 605 _state = _State.START; |
| 536 _messageType = _MessageType.UNDETERMINED; | 606 _messageType = _MessageType.UNDETERMINED; |
| 537 _headerField = new StringBuffer(); | 607 _headerField = new StringBuffer(); |
| 538 _headerValue = new StringBuffer(); | 608 _headerValue = new StringBuffer(); |
| 539 _method_or_status_code = new StringBuffer(); | 609 _method_or_status_code = new StringBuffer(); |
| 540 _uri_or_reason_phrase = new StringBuffer(); | 610 _uri_or_reason_phrase = new StringBuffer(); |
| 541 | 611 |
| 612 _httpVersion = _HttpVersion.UNDETERMINED; | |
| 542 _contentLength = -1; | 613 _contentLength = -1; |
| 543 _keepAlive = false; | 614 _persistentConnection = false; |
| 544 _connectionClose = false; | |
| 545 _connectionUpgrade = false; | 615 _connectionUpgrade = false; |
| 546 _chunked = false; | 616 _chunked = false; |
| 547 | 617 |
| 548 _noMessageBody = false; | 618 _noMessageBody = false; |
| 549 _responseToMethod = null; | 619 _responseToMethod = null; |
| 550 _remainingContent = null; | 620 _remainingContent = null; |
| 551 } | 621 } |
| 552 | 622 |
| 553 bool _isTokenChar(int byte) { | 623 bool _isTokenChar(int byte) { |
| 554 return byte > 31 && byte < 128 && _Const.SEPARATORS.indexOf(byte) == -1; | 624 return byte > 31 && byte < 128 && _Const.SEPARATORS.indexOf(byte) == -1; |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 597 } | 667 } |
| 598 | 668 |
| 599 int _state; | 669 int _state; |
| 600 int _httpVersionIndex; | 670 int _httpVersionIndex; |
| 601 int _messageType; | 671 int _messageType; |
| 602 StringBuffer _method_or_status_code; | 672 StringBuffer _method_or_status_code; |
| 603 StringBuffer _uri_or_reason_phrase; | 673 StringBuffer _uri_or_reason_phrase; |
| 604 StringBuffer _headerField; | 674 StringBuffer _headerField; |
| 605 StringBuffer _headerValue; | 675 StringBuffer _headerValue; |
| 606 | 676 |
| 677 int _httpVersion; | |
| 607 int _contentLength; | 678 int _contentLength; |
| 608 bool _keepAlive; | 679 bool _persistentConnection; |
| 609 bool _connectionClose; | |
| 610 bool _connectionUpgrade; | 680 bool _connectionUpgrade; |
| 611 bool _chunked; | 681 bool _chunked; |
| 612 | 682 |
| 613 bool _noMessageBody; | 683 bool _noMessageBody; |
| 614 String _responseToMethod; // Indicates the method used for the request. | 684 String _responseToMethod; // Indicates the method used for the request. |
| 615 int _remainingContent; | 685 int _remainingContent; |
| 616 | 686 |
| 617 // Callbacks. | 687 // Callbacks. |
| 618 Function requestStart; | 688 Function requestStart; |
| 619 Function responseStart; | 689 Function responseStart; |
| 620 Function headerReceived; | 690 Function headerReceived; |
| 621 Function headersComplete; | 691 Function headersComplete; |
| 622 Function dataReceived; | 692 Function dataReceived; |
| 623 Function dataEnd; | 693 Function dataEnd; |
| 624 Function error; | 694 Function error; |
| 625 } | 695 } |
| 626 | 696 |
| 627 | 697 |
| 628 class HttpParserException implements Exception { | 698 class HttpParserException implements Exception { |
| 629 const HttpParserException([String this.message = ""]); | 699 const HttpParserException([String this.message = ""]); |
| 630 String toString() => "HttpParserException: $message"; | 700 String toString() => "HttpParserException: $message"; |
| 631 final String message; | 701 final String message; |
| 632 } | 702 } |
| OLD | NEW |