Skip to content

Commit

Permalink
fixed HttpParser
Browse files Browse the repository at this point in the history
  • Loading branch information
quantmind committed Apr 8, 2013
1 parent e50164e commit d7257b5
Show file tree
Hide file tree
Showing 7 changed files with 61 additions and 45 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ examples/webmail/config.py
*~
.htmlprof
examples/djangoapp/test.db
test.pid
9 changes: 9 additions & 0 deletions examples/taskqueue/test_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,15 @@ def tearDownClass(cls):
yield send('arbiter', 'kill_actor', cls.name_tq())
yield send('arbiter', 'kill_actor', cls.name_rpc())

def test_rpc_job_list(self):
jobs = yield self.proxy.job_list()
self.assertTrue(jobs)
self.assertTrue(isinstance(jobs, list))
d = dict(jobs)
pycode = d['runpycode']
self.assertEqual(pycode['type'], 'regular')

class a:
@run_on_arbiter
def test_meta(self):
'''Tests meta attributes of taskqueue'''
Expand Down
8 changes: 3 additions & 5 deletions examples/webmail/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,14 @@
from pulsar.utils.pep import to_bytes, to_string
from pulsar.apps.test import unittest, dont_run_with_thread

from .manage import twisted, config
from .manage import twisted, mail_client


@unittest.skipUnless(twisted and config, 'Requires twisted and a config file')
@unittest.skipUnless(twisted, 'Requires twisted and a config file')
class TestWebMail(unittest.TestCase):
concurrency = 'thread'
server = None

def testMailCient(self):
client = mail_client(timeout=5)
yield client
client = client.result
client = yield mail_client(timeout=5)
self.assertTrue(client)
10 changes: 6 additions & 4 deletions pulsar/apps/http/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ def recv_body(self):
return self.parser.recv_body()

def get_content(self):
'''Retrive the body without flushing'''
'''Retrieve the body without flushing'''
b = self.parser.recv_body()
if b:
self._content = self._content + b if self._content else b
Expand Down Expand Up @@ -600,10 +600,12 @@ def build_protocol(self, address, timeout):
return create_connection(address, timeout)

def can_reuse_connection(self, connection, response):
# Reuse connection only if the headers has Connection keep-alive
if response and response.headers:
return response.headers.get('connection') == 'keep-alive'
else:
return False
for c in response.headers.get_all('connection', ()):
if c.lower() == 'keep-alive':
return True
return False

def upgrade(self, protocol):
'''Upgrade the protocol to another one'''
Expand Down
39 changes: 25 additions & 14 deletions pulsar/apps/wsgi/content.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
from functools import partial

from pulsar import Deferred, multi_async, is_async, maybe_async, is_failure
from pulsar.utils.pep import iteritems, is_string
from pulsar.utils.pep import iteritems, is_string, ispy3k
from pulsar.utils.structures import AttributeDictionary
from pulsar.utils.html import slugify, INLINE_TAGS, tag_attributes, attr_iter,\
csslink, dump_data_value, child_tag
Expand Down Expand Up @@ -64,17 +64,27 @@ def _handle_value(self, value):
else:
return value


def stream_to_string(stream):
for value in stream:
if value is None:
continue
elif isinstance(value, bytes):
yield value.decode('utf-8')
elif isinstance(value, str):
yield value
else:
yield str(value)
if ispy3k:
def stream_to_string(stream):
for value in stream:
if value is None:
continue
elif isinstance(value, bytes):
yield value.decode('utf-8')
elif isinstance(value, str):
yield value
else:
yield str(value)

else: #pragma nocover
def stream_to_string(stream):
for value in stream:
if value is None:
continue
elif isinstance(value, unicode):
yield value
else:
yield str(value)


class AsyncString(object):
Expand Down Expand Up @@ -161,9 +171,10 @@ def render(self, request=None):

def to_string(self, stream):
'''Once the stream is ready (no more asynchronous elements) this
functions get called to transform the stream into a string.
functions get called to transform the stream into a string. This method
can be overwritten by derived classes.
:param stream: a collections containg data used to build the string.
:param stream: a collections containing data used to build the string.
:return: a string or bytes
'''
return ''.join(stream_to_string(stream))
Expand Down
6 changes: 3 additions & 3 deletions pulsar/utils/httpurl.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
from collections import deque
from copy import copy

from .structures import mapping_iterator
from .structures import mapping_iterator, OrderedDict
from .pep import ispy3k, ispy26

create_connection = socket.create_connection
Expand Down Expand Up @@ -794,7 +794,7 @@ def __init__(self, kind=2, decompress=False):
self._query_string = None
self._kind = kind
self._fragment= None
self._headers = {}
self._headers = OrderedDict()
self._chunked = False
self._body = []
self._trailers = None
Expand Down Expand Up @@ -1006,7 +1006,7 @@ def _parse_headers(self, data):
name = name.rstrip(" \t").upper()
if HEADER_RE.search(name):
raise InvalidHeader("invalid header name %s" % name)
name, value = name.strip(), [value.lstrip()]
name, value = name.strip().lower(), [value.lstrip()]
# Consume value continuation lines
while len(lines) and lines[0].startswith((" ", "\t")):
value.append(lines.popleft())
Expand Down
33 changes: 14 additions & 19 deletions tests/http/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,17 +69,7 @@ def available_on_error(self):


class TestHttpClient(TestHttpClientBase, unittest.TestCase):

def test_http11(self):
'''By default HTTP/1.1 keep alive the connection if no keep-alive header
was passed by the client.'''
http = self.client()
http.headers.clear()
self.assertEqual(http.version, 'HTTP/1.1')
response = yield http.get(self.httpbin()).on_finished
self.assertEqual(response.headers['connection'], 'keep-alive')
self._check_pool(http, response)


def test_http10(self):
'''By default HTTP/1.0 close the connection if no keep-alive header
was passedby the client.'''
Expand All @@ -88,8 +78,19 @@ def test_http10(self):
self.assertEqual(http.version, 'HTTP/1.0')
response = yield http.get(self.httpbin()).on_finished
self.assertEqual(response.headers['connection'], 'close')
self.assertEqual(str(response), '200 OK')
self._check_pool(http, response, available=0)


def test_http11(self):
'''By default HTTP/1.1 keep alive the connection if no keep-alive header
was passed by the client.'''
http = self.client()
http.headers.clear()
self.assertEqual(http.version, 'HTTP/1.1')
response = yield http.get(self.httpbin()).on_finished
self.assertEqual(response.headers['connection'], 'keep-alive')
self._check_pool(http, response)

def testClient(self):
http = self.client(max_redirects=5, timeout=33)
self.assertTrue('accept-encoding' in http.headers)
Expand All @@ -98,7 +99,7 @@ def testClient(self):
self.assertEqual(http.max_redirects, 5)
if self.with_proxy:
self.assertEqual(http.proxy_info, {'http': self.proxy_uri})

def test_200_get(self):
http = self.client()
response = yield http.get(self.httpbin()).on_finished
Expand All @@ -114,12 +115,6 @@ def test_200_get(self):
self.assertEqual(response.status_code, 200)
self._check_pool(http, response, processed=2)

def test_http10(self):
http = self.client(version='HTTP/1.0')
self.assertEqual(http.version, 'HTTP/1.0')
response = yield http.get(self.httpbin()).on_finished
self._check_pool(http, response)

def test_HttpResponse(self):
r = HttpResponse(None)
self.assertEqual(r.current_request, None)
Expand Down

0 comments on commit d7257b5

Please sign in to comment.