Remove simplejson from staticweb

Since we're dropping Python 2.6 support, we can rely on stdlib's json
and get rid of our dependency on simplejson.

This lets us get rid of some redundant Unicode encoding. Before, we
would take the container-listing response off the wire,
JSON-deserialize it (str -> unicode), then pass each of several fields
from each entry to get_valid_utf8_str(), which would encode it,
(unicode -> str), decode it (str -> unicode), and then encode it again
(unicode -> str) for good measure.

The net effect was that each object's name would, in the proxy server,
go str -> unicode -> str -> unicode -> str.

By replacing simplejson with stdlib json, we get a guarantee that each
container-listing entry's name, hash, content_type, and last_modified
are unicodes, so we can stop worrying about them being valid UTF-8 or
not. This takes an encode and decode out of the path, so we just have
str -> unicode -> str. While it'd be ideal to avoid this, the first
transform (str -> unicode) happens when we decode the
container-listing response body (json.loads()), so there's no way out.

Change-Id: I00aedf952d691a809c23025b89131ea0f02b6431
This commit is contained in:
Samuel Merritt 2015-05-26 16:19:54 -07:00 committed by Alistair Coles
parent 15fd063ac3
commit 38787d0fb5
2 changed files with 11 additions and 33 deletions

View File

@ -117,10 +117,11 @@ Example usage of this middleware via ``swift``:
import cgi
import json
import time
from swift.common.utils import human_readable, split_path, config_true_value, \
json, quote, get_valid_utf8_str, register_swift_info
quote, register_swift_info
from swift.common.wsgi import make_pre_authed_env, WSGIContext
from swift.common.http import is_success, is_redirection, HTTP_NOT_FOUND
from swift.common.swob import Response, HTTPMovedPermanently, HTTPNotFound
@ -289,7 +290,7 @@ class _StaticWebContext(WSGIContext):
' </tr>\n'
for item in listing:
if 'subdir' in item:
subdir = get_valid_utf8_str(item['subdir'])
subdir = item['subdir'].encode("utf-8")
if prefix:
subdir = subdir[len(prefix):]
body += ' <tr class="item subdir">\n' \
@ -300,13 +301,14 @@ class _StaticWebContext(WSGIContext):
(quote(subdir), cgi.escape(subdir))
for item in listing:
if 'name' in item:
name = get_valid_utf8_str(item['name'])
name = item['name'].encode("utf-8")
if prefix:
name = name[len(prefix):]
content_type = get_valid_utf8_str(item['content_type'])
bytes = get_valid_utf8_str(human_readable(item['bytes']))
last_modified = (cgi.escape(item['last_modified']).
split('.')[0].replace('T', ' '))
content_type = item['content_type'].encode("utf-8")
bytes = human_readable(item['bytes'])
last_modified = (
cgi.escape(item['last_modified'].encode("utf-8")).
split('.')[0].replace('T', ' '))
body += ' <tr class="item %s">\n' \
' <td class="colname"><a href="%s">%s</a></td>\n' \
' <td class="colsize">%s</td>\n' \
@ -315,7 +317,7 @@ class _StaticWebContext(WSGIContext):
(' '.join('type-' + cgi.escape(t.lower(), quote=True)
for t in content_type.split('/')),
quote(name), cgi.escape(name),
bytes, get_valid_utf8_str(last_modified))
bytes, last_modified)
body += ' </table>\n' \
' </body>\n' \
'</html>\n'

View File

@ -13,15 +13,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
try:
import simplejson as json
except ImportError:
import json
import json as stdlib_json
import json
import unittest
import mock
from swift.common.swob import Request, Response
from swift.common.middleware import staticweb
@ -699,24 +693,6 @@ class TestStaticWeb(unittest.TestCase):
self.assert_('listing.css' not in resp.body)
self.assert_('<style' in resp.body)
def test_container_unicode_stdlib_json(self):
with mock.patch('swift.common.middleware.staticweb.json',
new=stdlib_json):
resp = Request.blank(
'/v1/a/c10/').get_response(self.test_staticweb)
self.assertEquals(resp.status_int, 200)
self.assert_('Listing of /v1/a/c10/' in resp.body)
resp = Request.blank(
'/v1/a/c10/\xe2\x98\x83/').get_response(self.test_staticweb)
self.assertEquals(resp.status_int, 200)
self.assert_('Listing of /v1/a/c10/\xe2\x98\x83/' in resp.body)
resp = Request.blank(
'/v1/a/c10/\xe2\x98\x83/\xe2\x98\x83/'
).get_response(self.test_staticweb)
self.assertEquals(resp.status_int, 200)
self.assert_(
'Listing of /v1/a/c10/\xe2\x98\x83/\xe2\x98\x83/' in resp.body)
def test_subrequest_once_if_possible(self):
resp = Request.blank(
'/v1/a/c4/one.txt').get_response(self.test_staticweb)