import logging
import socket
import sys
+import re
from tornado import ioloop
from tornado import stack_context
self._read_buffer_size = 0
self._write_buffer_frozen = False
self._read_delimiter = None
+ self._read_regex = None
self._read_bytes = None
self._read_until_close = False
self._read_callback = None
self._connect_callback = stack_context.wrap(callback)
self._add_io_state(self.io_loop.WRITE)
+ def read_until_regex(self, regex, callback):
+ """Call callback when we read the given regex pattern."""
+ assert not self._read_callback, "Already reading"
+ self._read_regex = re.compile(regex)
+ self._read_callback = stack_context.wrap(callback)
+ while True:
+ # See if we've already got the data from a previous read
+ if self._read_from_buffer():
+ return
+ self._check_closed()
+ if self._read_to_buffer() == 0:
+ break
+ self._add_io_state(self.io_loop.READ)
+
def read_until(self, delimiter, callback):
"""Call callback when we read the given delimiter."""
assert not self._read_callback, "Already reading"
self._run_callback(callback,
self._consume(loc + delimiter_len))
return True
+ elif self._read_regex is not None:
+ _merge_prefix(self._read_buffer, sys.maxint)
+ m = self._read_regex.search(self._read_buffer[0])
+ if m:
+ callback = self._read_callback
+ self._read_callback = None
+ self._read_regex = None
+ self._run_callback(callback, self._consume(m.end()))
+ return True
return False
def _handle_connect(self):
self.stream.write(b("\r\n").join(request_lines) + b("\r\n\r\n"))
if self.request.body is not None:
self.stream.write(self.request.body)
- self.stream.read_until(b("\r\n\r\n"), self._on_headers)
+ self.stream.read_until_regex(b("\r?\n\r?\n"), self._on_headers)
def _release(self):
if self.release_callback is not None:
def _on_headers(self, data):
data = native_str(data.decode("latin1"))
- first_line, _, header_data = data.partition("\r\n")
+ first_line, _, header_data = data.partition("\n")
match = re.match("HTTP/1.[01] ([0-9]+)", first_line)
assert match
self.code = int(match.group(1))