Browse Source

Improve boolean HTTP parameter handling

tags/nilmdb-1.8.2^0
Jim Paris 10 years ago
parent
commit
d6d215d53d
4 changed files with 51 additions and 11 deletions
  1. +7
    -0
      nilmdb/server/server.py
  2. +15
    -0
      nilmdb/server/serverutil.py
  3. +9
    -2
      nilmdb/utils/unicode.py
  4. +20
    -9
      tests/test_client.py

+ 7
- 0
nilmdb/server/server.py View File

@@ -27,6 +27,7 @@ from nilmdb.server.serverutil import (
json_error_page,
cherrypy_start,
cherrypy_stop,
bool_param,
)

# Add CORS_allow tool
@@ -221,6 +222,8 @@ class Stream(NilmApp):
little-endian and matches the database types (including an
int64 timestamp).
"""
binary = bool_param(binary)

# Important that we always read the input before throwing any
# errors, to keep lengths happy for persistent connections.
# Note that CherryPy 3.2.2 has a bug where this fails for GET
@@ -345,6 +348,10 @@ class Stream(NilmApp):
little-endian and matches the database types (including an
int64 timestamp).
"""
binary = bool_param(binary)
markup = bool_param(markup)
count = bool_param(count)

(start, end) = self._get_times(start, end)

# Check path and get layout


+ 15
- 0
nilmdb/server/serverutil.py View File

@@ -7,6 +7,21 @@ import os
import decorator
import simplejson as json

# Helper to parse parameters into booleans
def bool_param(s):
"""Return a bool indicating whether parameter 's' was True or False,
supporting a few different types for 's'."""
try:
ss = s.lower()
if ss in [ "0", "false", "f", "no", "n" ]:
return False
if ss in [ "1", "true", "t", "yes", "y" ]:
return True
except Exception:
return bool(s)
raise cherrypy.HTTPError("400 Bad Request",
"can't parse parameter: " + ss)

# Decorators
def chunked_response(func):
"""Decorator to enable chunked responses."""


+ 9
- 2
nilmdb/utils/unicode.py View File

@@ -1,7 +1,14 @@
import sys

if sys.version_info[0] >= 3: # pragma: no cover (future Python3 compat)
text_type = str
else:
text_type = unicode

def encode(u):
"""Try to encode something from Unicode to a string using the
default encoding. If it fails, try encoding as UTF-8."""
if not isinstance(u, unicode):
if not isinstance(u, text_type):
return u
try:
return u.encode()
@@ -11,7 +18,7 @@ def encode(u):
def decode(s):
"""Try to decode someting from string to Unicode using the
default encoding. If it fails, try decoding as UTF-8."""
if isinstance(s, unicode):
if isinstance(s, text_type):
return s
try:
return s.decode()


+ 20
- 9
tests/test_client.py View File

@@ -392,27 +392,38 @@ class TestClient(object):
headers())

# Extract
x = http.get("stream/extract",
{ "path": "/newton/prep",
"start": "123",
"end": "124" })
x = http.get("stream/extract", { "path": "/newton/prep",
"start": "123", "end": "124" })
if "transfer-encoding: chunked" not in headers():
warnings.warn("Non-chunked HTTP response for /stream/extract")
if "content-type: text/plain;charset=utf-8" not in headers():
raise AssertionError("/stream/extract is not text/plain:\n" +
headers())

x = http.get("stream/extract",
{ "path": "/newton/prep",
"start": "123",
"end": "124",
"binary": "1" })
x = http.get("stream/extract", { "path": "/newton/prep",
"start": "123", "end": "124",
"binary": "1" })
if "transfer-encoding: chunked" not in headers():
warnings.warn("Non-chunked HTTP response for /stream/extract")
if "content-type: application/octet-stream" not in headers():
raise AssertionError("/stream/extract is not binary:\n" +
headers())

# Make sure a binary of "0" is really off
x = http.get("stream/extract", { "path": "/newton/prep",
"start": "123", "end": "124",
"binary": "0" })
if "content-type: application/octet-stream" in headers():
raise AssertionError("/stream/extract is not text:\n" +
headers())

# Invalid parameters
with assert_raises(ClientError) as e:
x = http.get("stream/extract", { "path": "/newton/prep",
"start": "123", "end": "124",
"binary": "asdfasfd" })
in_("can't parse parameter", str(e.exception))

client.close()

def test_client_08_unicode(self):


Loading…
Cancel
Save