Skip to content
Browse files

Fix various http get/post related defects

Also added more tests (which found most of the defects in the first
place).
  • Loading branch information...
1 parent d29a206 commit 765ba72f7be07100a7fcb8ccc78ef1fef7b16327 @jmcfarlane committed Nov 10, 2011
View
14 apps/example/webapp/controller/http.py
@@ -0,0 +1,14 @@
+from chula.www import controller
+
+class Http(controller.Controller):
+ def _format(self, d):
+ return '\n'.join('%s==%s' % (k,v) for k,v in d.items())
+
+ def render_form(self):
+ return self._format(self.env.form)
+
+ def render_form_get(self):
+ return self._format(self.env.form_get)
+
+ def render_form_post(self):
+ return self._format(self.env.form_post)
View
21 chula/test/bat.py
@@ -1,7 +1,7 @@
-"""Class for use with Basic Acceptance Testing"""
+
# Python imports
-from urllib import urlencode
+import urllib
import os
import unittest
@@ -12,6 +12,7 @@
from chula import collection
PORT = os.environ.get('CHULA_TEST_PORT', 8090)
+PROVIDER = os.environ.get('CHULA_TEST_PROVIDER', 'builtin')
class Bat(unittest.TestCase):
def response(self, request):
@@ -30,9 +31,21 @@ def get(self, url):
return self.response(http.request(self.url(url), 'GET'))
def post(self, url, data):
+ # For some reason chula is responding oddly to http POST
+ # variables when requested by httplib2. It responds fine with
+ # urllib or curl. Using urllib for a bit longer (for this
+ # method only.
+ data = urllib.urlencode(data)
+ response = urllib.urlopen(self.url(url), data)
+ retval = collection.Collection()
+ retval.data = response.read()
+ retval.status = response.code
+ retval.headers = response.info().headers
+ return retval
+
+ def post_file(self, url, body):
http = httplib2.Http()
- data = urlencode(data)
- return self.response(http.request(self.url(url), 'POST', data))
+ return self.response(http.request(self.url(url), 'POST', body=body))
def put(self, url, body, headers=None):
http = httplib2.Http()
View
25 chula/www/adapters/env.py
@@ -209,7 +209,10 @@ def _clean_http_vars(self):
# Cast any dict-like objects (FieldStorage for example) to
# real dicts, so method like get() and iteritems() exist.
- self.form = dict(self.form)
+ try:
+ self.form = dict(self.form)
+ except TypeError:
+ self.form = {}
# Create object to hold only HTTP GET variables
self.form_get = cgi.parse_qs(self.QUERY_STRING, keep_blank_values=1)
@@ -232,13 +235,19 @@ def _clean_http_vars(self):
# Create an object to hold only HTTP POST variables
self.form_post = {}
- passed = deepcopy(self.form)
- for key in passed.keys():
- if not key in self.form_get:
- if isinstance(passed[key], list):
- self.form_post[key] = passed[key]
- else:
- self.form_post[key] = passed[key].value
+ for key in self.form:
+ if isinstance(self.form[key], list):
+ self.form_post[key] = [k.value for k in self.form[key]]
+ if key in self.form_get:
+ for v in self.form_get[key]:
+ self.form_post[key].remove(v)
+
+ if isinstance(self.form_post[key], list):
+ if len(self.form_post[key]) == 1:
+ self.form_post[key] = self.form_post[key].pop()
+
+ else:
+ self.form_post[key] = self.form[key].value
# Make sure the form object contains both while taking
# precedence over POST when overlap exists
View
1 docs/changelog.rst
@@ -19,6 +19,7 @@ Chula v0.13.0 (dev)
- Add support for using the Eventlet wsgi provider.
- Switch to httplib2 when running bat tests.
+- Fix various http GET/POST bugs.
:Source: http://github.com/jmcfarlane/chula
View
5 scripts/run_tests
@@ -22,8 +22,9 @@ if __name__ == "__main__":
path = os.getcwd()
# Start up the webserver
- sys.argv.append('-p %s' % bat.PORT)
- sys.argv.append('%s' % webapp)
+ sys.argv.extend(['--port', bat.PORT])
+ sys.argv.extend(['--provider', bat.PROVIDER])
+ sys.argv.extend([webapp])
proc = multiprocessing.Process(target=app.run)
proc.start()
proc.join(1)
View
86 tests/bat/test_http.py
@@ -0,0 +1,86 @@
+from chula.test import bat
+
+HTML = 'Hello <a href="home/foo">world</a>'
+
+class Test_http(bat.Bat):
+ def test_get(self):
+ retval = self.get('')
+ self.assertEquals(retval.data, HTML)
+ self.assertEquals(retval.status, 200)
+
+ def test_get_args_in_form_get(self):
+ retval = self.get('/http/render_form?a=b&foo=bar')
+ self.assertTrue('a==b' in retval.data, retval.data)
+ self.assertTrue('foo==bar' in retval.data, retval.data)
+ self.assertEquals(retval.status, 200)
+
+ def test_get_args_in_form(self):
+ retval = self.get('/http/render_form_get?a=b&foo=bar')
+ self.assertTrue('a==b' in retval.data, retval.data)
+ self.assertTrue('foo==bar' in retval.data, retval.data)
+ self.assertEquals(retval.status, 200)
+
+ def test_get_args_multiple(self):
+ retval = self.get('/http/render_form_get?a=b&a=c')
+ self.assertTrue("a==['b', 'c']" in retval.data, retval.data)
+ self.assertEquals(retval.status, 200)
+
+ def test_post(self):
+ retval = self.post('', dict(a='a', b='b'))
+ self.assertEquals(retval.data, HTML)
+
+ def test_post_args_in_form_post(self):
+ data = dict(a='b', foo='bar')
+ retval = self.post('/http/render_form_post', data)
+ self.assertTrue('a==b' in retval.data, retval)
+ self.assertTrue('foo==bar' in retval.data, retval.data)
+ self.assertEquals(retval.status, 200)
+
+ def test_post_args_in_form(self):
+ data = dict(a='b', foo='bar')
+ retval = self.post('/http/render_form', data)
+ self.assertTrue('a==b' in retval.data, retval)
+ self.assertTrue('foo==bar' in retval.data, retval.data)
+ self.assertEquals(retval.status, 200)
+
+ def test_post_and_get_args(self):
+ data = dict(a='b', foo='bar')
+ retval = self.post('/http/render_form?x=y&car=red', data)
+ self.assertTrue('a==b' in retval.data, retval)
+ self.assertTrue('foo==bar' in retval.data, retval.data)
+ self.assertTrue('x==y' in retval.data, retval)
+ self.assertTrue('car==red' in retval.data, retval)
+ self.assertEquals(retval.status, 200)
+
+ def test_post_and_get_args_that_overlap(self):
+ data = dict(a='A', foo='bar')
+ retval = self.post('/http/render_form?a=b', data)
+ self.assertTrue('a==A' in retval.data, retval)
+ self.assertTrue('foo==bar' in retval.data, retval.data)
+ self.assertEquals(retval.status, 200)
+
+ def test_post_args_isolated_from_get(self):
+ data = dict(a='A', foo='bar')
+ retval = self.post('/http/render_form_post?a=b', data)
+ self.assertTrue('a==A' in retval.data, retval)
+ self.assertTrue('foo==bar' in retval.data, retval.data)
+ self.assertEquals(retval.status, 200)
+
+ def test_get_args_isolated_from_post(self):
+ data = dict(a='A', foo='bar')
+ retval = self.post('/http/render_form_get?a=b', data)
+ self.assertTrue('a==b' in retval.data, retval)
+ self.assertTrue('foo==bar' not in retval.data, retval.data)
+ self.assertEquals(retval.status, 200)
+
+ def test_put(self):
+ retval = self.put('', 'this is plain text')
+ self.assertEquals(retval.data, HTML)
+ self.assertEquals(retval.status, 200)
+ self.assertEquals(retval.status, 200)
+
+ def test_delete(self):
+ retval = self.put('', '<delete>me</delete>')
+ self.assertEquals(retval.data, HTML)
+ self.assertEquals(retval.status, 200)
+ self.assertEquals(retval.status, 200)
View
35 tests/bat/test_mime_type_multipart.py
@@ -0,0 +1,35 @@
+# Python imports
+from subprocess import Popen, PIPE
+import hashlib
+
+# Project imports
+from chula.test import bat
+
+HANDLER = '/http/render_form_post'
+HTML = 'Hello <a href="home/foo">world</a>'
+
+def shell(cmd):
+ output = Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE)
+ return output.communicate()
+
+class Test_mime_type_multipart(bat.Bat):
+ def _post_and_validate_checksum(self, b, a):
+ cmd = 'curl -v -F file=@%s %s' % (b, self.url(HANDLER))
+ stdout, stderr = shell(cmd)
+ open(a, 'w').write(stdout[len('file=='):])
+ before = hashlib.sha1(open(b).read()).hexdigest()
+ after = hashlib.sha1(open(a).read()).hexdigest()
+ self.assertEquals(before, after, stderr)
+
+ def test_text_file(self):
+ sample = 'SAMPLE TEXT FILE'
+ open('/tmp/test.txt', 'w').write(sample)
+ cmd = 'curl -v -F file=@/tmp/test.txt %s' % self.url(HANDLER)
+ stdout, stderr = shell(cmd)
+ self.assertEquals(stdout, 'file==%s' % sample, stderr)
+
+ def test_text_file_without_extension(self):
+ self._post_and_validate_checksum('/etc/services', '/tmp/services')
+
+ def test_binary_file_without_extension(self):
+ self._post_and_validate_checksum('/bin/echo', '/tmp/echo')

0 comments on commit 765ba72

Please sign in to comment.
Something went wrong with that request. Please try again.