示例#1
0
    def test_multipart(self):
        text_part = ntou('This is the text version')
        html_part = ntou(
            """<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
 <meta content="text/html;charset=ISO-8859-1" http-equiv="Content-Type">
</head>
<body bgcolor="#ffffff" text="#000000">

This is the <strong>HTML</strong> version
</body>
</html>
""")
        body = '\r\n'.join([
            '--123456789',
            "Content-Type: text/plain; charset='ISO-8859-1'",
            'Content-Transfer-Encoding: 7bit',
            '',
            text_part,
            '--123456789',
            "Content-Type: text/html; charset='ISO-8859-1'",
            '',
            html_part,
            '--123456789--'])
        headers = [
            ('Content-Type', 'multipart/mixed; boundary=123456789'),
            ('Content-Length', str(len(body))),
        ]
        self.getPage('/multipart', headers, 'POST', body)
        self.assertBody(repr([text_part, html_part]))
示例#2
0
 def test_multipart_form_data(self):
     body = '\r\n'.join([
         '--X',
         'Content-Disposition: form-data; name="foo"',
         '',
         'bar',
         '--X',
         # Test a param with more than one value.
         # See
         # https://github.com/cherrypy/cherrypy/issues/1028
         'Content-Disposition: form-data; name="baz"',
         '',
         '111',
         '--X',
         'Content-Disposition: form-data; name="baz"',
         '',
         '333',
         '--X--'
     ])
     self.getPage('/multipart_form_data', method='POST',
                  headers=[(
                      'Content-Type', 'multipart/form-data;boundary=X'),
                      ('Content-Length', str(len(body))),
                  ],
                  body=body),
     self.assertBody(
         repr([('baz', [ntou('111'), ntou('333')]), ('foo', ntou('bar'))]))
示例#3
0
 def __call__(self, environ, start_response):
     # If you're calling this, then you're probably setting SCRIPT_NAME
     # to '' (some WSGI servers always set SCRIPT_NAME to '').
     # Try to look up the app using the full path.
     env1x = environ
     if environ.get(ntou('wsgi.version')) == (ntou('u'), 0):
         env1x = _cpwsgi.downgrade_wsgi_ux_to_1x(environ)
     path = httputil.urljoin(env1x.get('SCRIPT_NAME', ''),
                             env1x.get('PATH_INFO', ''))
     sn = self.script_name(path or "/")
     if sn is None:
         start_response('404 Not Found', [])
         return []
     
     app = self.apps[sn]
     
     # Correct the SCRIPT_NAME and PATH_INFO environ entries.
     environ = environ.copy()
     if environ.get(u'wsgi.version') == (u'u', 0):
         # Python 2/WSGI u.0: all strings MUST be of type unicode
         enc = environ[u'wsgi.url_encoding']
         environ[u'SCRIPT_NAME'] = sn.decode(enc)
         environ[u'PATH_INFO'] = path[len(sn.rstrip("/")):].decode(enc)
     else:
         # Python 2/WSGI 1.x: all strings MUST be of type str
         environ['SCRIPT_NAME'] = sn
         environ['PATH_INFO'] = path[len(sn.rstrip("/")):]
     return app(environ, start_response)
示例#4
0
    def test_multipart(self):
        text_part = ntou("This is the text version")
        html_part = ntou("""<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
 <meta content="text/html;charset=ISO-8859-1" http-equiv="Content-Type">
</head>
<body bgcolor="#ffffff" text="#000000">

This is the <strong>HTML</strong> version
</body>
</html>
""")
        body = '\r\n'.join([
            "--123456789",
            "Content-Type: text/plain; charset='ISO-8859-1'",
            "Content-Transfer-Encoding: 7bit",
            "",
            text_part,
            "--123456789",
            "Content-Type: text/html; charset='ISO-8859-1'",
            "",
            html_part,
            "--123456789--"])
        headers = [
            ('Content-Type', 'multipart/mixed; boundary=123456789'),
            ('Content-Length', str(len(body))),
            ]
        self.getPage('/multipart', headers, "POST", body)
        self.assertBody(repr([text_part, html_part]))
示例#5
0
 def test_multipart_form_data(self):
     body = '\r\n'.join([
         '--X',
         'Content-Disposition: form-data; name="foo"',
         '',
         'bar',
         '--X',
         # Test a param with more than one value.
         # See
         # https://bitbucket.org/cherrypy/cherrypy/issue/1028
         'Content-Disposition: form-data; name="baz"',
         '',
         '111',
         '--X',
         'Content-Disposition: form-data; name="baz"',
         '',
         '333',
         '--X--'
     ])
     self.getPage('/multipart_form_data',
                  method='POST',
                  headers=[
                      ("Content-Type", "multipart/form-data;boundary=X"),
                      ("Content-Length", str(len(body))),
                  ],
                  body=body),
     self.assertBody(
         repr([('baz', [ntou('111'), ntou('333')]), ('foo', ntou('bar'))]))
示例#6
0
def json_processor(entity):
    """Read application/json data into request.json."""
    if not entity.headers.get(ntou('Content-Length'), ntou('')):
        raise cherrypy.HTTPError(411)

    body = entity.fp.read()
    with cherrypy.HTTPError.handle(ValueError, 400, 'Invalid JSON document'):
        cherrypy.serving.request.json = json.decode(body.decode('utf-8'))
示例#7
0
 def euro(self):
     hooks = list(cherrypy.request.hooks['before_finalize'])
     hooks.sort()
     cbnames = [ x.callback.__name__ for x in hooks ]
     priorities = [ x.priority for x in hooks ]
     yield ntou('Hello,')
     yield ntou('world')
     yield europoundUnicode
示例#8
0
 def euro(self):
     hooks = list(cherrypy.request.hooks['before_finalize'])
     hooks.sort()
     cbnames = [x.callback.__name__ for x in hooks]
     priorities = [x.priority for x in hooks]
     yield ntou('Hello,')
     yield ntou('world')
     yield europoundUnicode
示例#9
0
def json_processor(entity):
    if not entity.headers.get(ntou('Content-Length'), ntou('')):
        raise cherrypy.HTTPError(411)
    body = entity.fp.read()
    try:
        cherrypy.serving.request.json = json_decode(body.decode('utf-8'))
    except ValueError:
        raise cherrypy.HTTPError(400, 'Invalid JSON document')
示例#10
0
def json_processor(entity):
    if not entity.headers.get(ntou('Content-Length'), ntou('')):
        raise cherrypy.HTTPError(411)
    body = entity.fp.read()
    try:
        cherrypy.serving.request.json = json_decode(body.decode('utf-8'))
    except ValueError:
        raise cherrypy.HTTPError(400, 'Invalid JSON document')
示例#11
0
def json_processor(entity):
    """Read application/json data into request.json."""
    if not entity.headers.get(ntou('Content-Length'), ntou('')):
        raise cherrypy.HTTPError(411)

    body = entity.fp.read()
    with cherrypy.HTTPError.handle(ValueError, 400, 'Invalid JSON document'):
        cherrypy.serving.request.json = json_decode(body.decode('utf-8'))
示例#12
0
 def unicode_file():
     filename = ntou("Слава Україні.html", 'utf-8')
     filepath = os.path.join(curdir, "static", filename)
     with io.open(filepath, 'w', encoding='utf-8') as strm:
         strm.write(ntou("Героям Слава!", 'utf-8'))
     try:
         yield
     finally:
         os.remove(filepath)
示例#13
0
 def unicode_file():
     filename = ntou('Слава Україні.html', 'utf-8')
     filepath = os.path.join(curdir, 'static', filename)
     with io.open(filepath, 'w', encoding='utf-8') as strm:
         strm.write(ntou('Героям Слава!', 'utf-8'))
     try:
         yield
     finally:
         os.remove(filepath)
示例#14
0
    def test_unicode(self):
        url = ntou("/static/Слава Україні.html", 'utf-8')
        # quote function requires str
        url = tonative(url, 'utf-8')
        url = urllib.parse.quote(url)
        self.getPage(url)

        expected = ntou("Героям Слава!", 'utf-8')
        self.assertInBody(expected)
示例#15
0
 def euro(self):
     hooks = list(cherrypy.request.hooks['before_finalize'])
     hooks.sort()
     cbnames = [x.callback.__name__ for x in hooks]
     assert cbnames == ['gzip'], cbnames
     priorities = [x.priority for x in hooks]
     assert priorities == [80], priorities
     yield ntou("Hello,")
     yield ntou("world")
     yield europoundUnicode
示例#16
0
 def euro(self):
     hooks = list(cherrypy.request.hooks['before_finalize'])
     hooks.sort()
     cbnames = [x.callback.__name__ for x in hooks]
     assert cbnames == ['gzip'], cbnames
     priorities = [x.priority for x in hooks]
     assert priorities == [80], priorities
     yield ntou("Hello,")
     yield ntou("world")
     yield europoundUnicode
示例#17
0
def json_processor(entity):
    """Read application/json data into request.json."""
    if not entity.headers.get(ntou("Content-Length"), ntou("")):
        raise cherrypy.HTTPError(411)

    body = entity.fp.read()
    try:
        cherrypy.serving.request.json = json_decode(body.decode('utf-8'))
    except ValueError:
        raise cherrypy.HTTPError(400, 'Invalid JSON document')
示例#18
0
    def test_unicode(self):
        ensure_unicode_filesystem()
        with self.unicode_file():
            url = ntou('/static/Слава Україні.html', 'utf-8')
            # quote function requires str
            url = tonative(url, 'utf-8')
            url = urllib.parse.quote(url)
            self.getPage(url)

            expected = ntou('Героям Слава!', 'utf-8')
            self.assertInBody(expected)
示例#19
0
    def test_unicode(self):
        ensure_unicode_filesystem()
        self.unicode_file()
        url = ntou('/static/Слава Україні.html', 'utf-8')
        # quote function requires str
        url = tonative(url, 'utf-8')
        url = urllib.parse.quote(url)
        self.getPage(url)

        expected = ntou('Героям Слава!', 'utf-8')
        self.assertInBody(expected)
示例#20
0
def json_in(content_type = [ntou('application/json'), ntou('text/javascript')], force = True, debug = False, processor = json_processor):
    request = cherrypy.serving.request
    if isinstance(content_type, basestring):
        content_type = [content_type]
    if force:
        if debug:
            cherrypy.log('Removing body processors %s' % repr(request.body.processors.keys()), 'TOOLS.JSON_IN')
        request.body.processors.clear()
        request.body.default_proc = cherrypy.HTTPError(415, 'Expected an entity of content type %s' % ', '.join(content_type))
    for ct in content_type:
        if debug:
            cherrypy.log('Adding body processor for %s' % ct, 'TOOLS.JSON_IN')
        request.body.processors[ct] = processor
示例#21
0
def downgrade_wsgi_ux_to_1x(environ):
    """Return a new environ dict for WSGI 1.x from the given WSGI u.x environ."""
    env1x = {}
    
    url_encoding = environ[ntou('wsgi.url_encoding')]
    for k, v in list(environ.items()):
        if k in [ntou('PATH_INFO'), ntou('SCRIPT_NAME'), ntou('QUERY_STRING')]:
            v = v.encode(url_encoding)
        elif isinstance(v, unicodestr):
            v = v.encode('ISO-8859-1')
        env1x[k.encode('ISO-8859-1')] = v
    
    return env1x
示例#22
0
def downgrade_wsgi_ux_to_1x(environ):
    """Return a new environ dict for WSGI 1.x from the given WSGI u.x environ."""
    env1x = {}
    
    url_encoding = environ[ntou('wsgi.url_encoding')]
    for k, v in list(environ.items()):
        if k in [ntou('PATH_INFO'), ntou('SCRIPT_NAME'), ntou('QUERY_STRING')]:
            v = v.encode(url_encoding)
        elif isinstance(v, unicodestr):
            v = v.encode('ISO-8859-1')
        env1x[k.encode('ISO-8859-1')] = v
    
    return env1x
示例#23
0
 def test_multipart(self):
     text_part = ntou('This is the text version')
     html_part = ntou(
         '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">\n<html>\n<head>\n <meta content="text/html;charset=ISO-8859-1" http-equiv="Content-Type">\n</head>\n<body bgcolor="#ffffff" text="#000000">\n\nThis is the <strong>HTML</strong> version\n</body>\n</html>\n'
     )
     body = '\r\n'.join([
         '--123456789', "Content-Type: text/plain; charset='ISO-8859-1'",
         'Content-Transfer-Encoding: 7bit', '', text_part, '--123456789',
         "Content-Type: text/html; charset='ISO-8859-1'", '', html_part,
         '--123456789--'
     ])
     headers = [('Content-Type', 'multipart/mixed; boundary=123456789'),
                ('Content-Length', str(len(body)))]
     self.getPage('/multipart', headers, 'POST', body)
     self.assertBody(repr([text_part, html_part]))
示例#24
0
 def model_processor(entity):
     """Read application/json data into request.model."""
     if not entity.headers.get(ntou('Content-Length'),
                               ntou('')):  # pragma: no cover
         raise cherrypy.HTTPError(411)
     body = entity.fp.read()
     with cherrypy.HTTPError.handle(ValueError, 400,
                                    'Invalid JSON document'):
         model_json = json.decode(body.decode('utf-8'))
     try:
         model = cls(model_json)
         model.validate()
     except DataError as e:
         raise PayloadValidationError(e)
     cherrypy.serving.request.model = model
示例#25
0
    def testParams(self):
        self.getPage("/params/?thing=a")
        self.assertBody(repr(ntou("a")))

        self.getPage("/params/?thing=a&thing=b&thing=c")
        self.assertBody(repr([ntou('a'), ntou('b'), ntou('c')]))

        # Test friendly error message when given params are not accepted.
        cherrypy.config.update({"request.show_mismatched_params": True})
        self.getPage("/params/?notathing=meeting")
        self.assertInBody("Missing parameters: thing")
        self.getPage("/params/?thing=meeting&notathing=meeting")
        self.assertInBody("Unexpected query string parameters: notathing")

        # Test ability to turn off friendly error messages
        cherrypy.config.update({"request.show_mismatched_params": False})
        self.getPage("/params/?notathing=meeting")
        self.assertInBody("Not Found")
        self.getPage("/params/?thing=meeting&notathing=meeting")
        self.assertInBody("Not Found")

        # Test "% HEX HEX"-encoded URL, param keys, and values
        self.getPage("/params/%d4%20%e3/cheese?Gruy%E8re=Bulgn%e9ville")
        self.assertBody("args: %s kwargs: %s" %
                        (('\xd4 \xe3', 'cheese'), {
                            'Gruy\xe8re': ntou('Bulgn\xe9ville')
                        }))

        # Make sure that encoded = and & get parsed correctly
        self.getPage(
            "/params/code?url=http%3A//cherrypy.org/index%3Fa%3D1%26b%3D2")
        self.assertBody("args: %s kwargs: %s" %
                        (('code', ), {
                            'url': ntou('http://cherrypy.org/index?a=1&b=2')
                        }))

        # Test coordinates sent by <img ismap>
        self.getPage("/params/ismap?223,114")
        self.assertBody("Coordinates: 223, 114")

        # Test "name[key]" dict-like params
        self.getPage("/params/dictlike?a[1]=1&a[2]=2&b=foo&b[bar]=baz")
        self.assertBody("args: %s kwargs: %s" % (('dictlike', ), {
            'a[1]': ntou('1'),
            'b[bar]': ntou('baz'),
            'b': ntou('foo'),
            'a[2]': ntou('2')
        }))
示例#26
0
def _old_process_multipart(entity):
    """The behavior of 3.2 and lower. Deprecated and will be changed in 3.3."""
    process_multipart(entity)

    params = entity.params

    for part in entity.parts:
        if part.name is None:
            key = ntou('parts')
        else:
            key = part.name

        if part.filename is None:
            # It's a regular field
            value = part.fullvalue()
        else:
            # It's a file upload. Retain the whole part so consumer code
            # has access to its .file and .filename attributes.
            value = part

        if key in params:
            if not isinstance(params[key], list):
                params[key] = [params[key]]
            params[key].append(value)
        else:
            params[key] = value
示例#27
0
    def testMethodDispatch(self):
        self.getPage("/bymethod")
        self.assertBody("['another']")
        self.assertHeader('Allow', 'GET, HEAD, POST')

        self.getPage("/bymethod", method="HEAD")
        self.assertBody("")
        self.assertHeader('Allow', 'GET, HEAD, POST')

        self.getPage("/bymethod", method="POST", body="thing=one")
        self.assertBody("")
        self.assertHeader('Allow', 'GET, HEAD, POST')

        self.getPage("/bymethod")
        self.assertBody(repr(['another', ntou('one')]))
        self.assertHeader('Allow', 'GET, HEAD, POST')

        self.getPage("/bymethod", method="PUT")
        self.assertErrorPage(405)
        self.assertHeader('Allow', 'GET, HEAD, POST')

        # Test default with posparams
        self.getPage("/collection/silly", method="POST")
        self.getPage("/collection", method="GET")
        self.assertBody("['a', 'bit', 'silly']")

        # Test custom dispatcher set on app root (see #737).
        self.getPage("/app")
        self.assertBody("milk")
示例#28
0
    def testCombinedTools(self):
        expectedResult = (ntou("Hello,world") +
                          europoundUnicode).encode('utf-8')
        zbuf = BytesIO()
        zfile = gzip.GzipFile(mode='wb', fileobj=zbuf, compresslevel=9)
        zfile.write(expectedResult)
        zfile.close()

        self.getPage("/euro",
                     headers=[("Accept-Encoding", "gzip"),
                              ("Accept-Charset",
                               "ISO-8859-1,utf-8;q=0.7,*;q=0.7")])
        self.assertInBody(zbuf.getvalue()[:3])

        zbuf = BytesIO()
        zfile = gzip.GzipFile(mode='wb', fileobj=zbuf, compresslevel=6)
        zfile.write(expectedResult)
        zfile.close()

        self.getPage("/decorated_euro", headers=[("Accept-Encoding", "gzip")])
        self.assertInBody(zbuf.getvalue()[:3])

        # This returns a different value because gzip's priority was
        # lowered in conf, allowing the rotator to run after gzip.
        # Of course, we don't want breakage in production apps,
        # but it proves the priority was changed.
        self.getPage("/decorated_euro/subpath",
                     headers=[("Accept-Encoding", "gzip")])
        self.assertInBody(bytes([(x + 3) % 256 for x in zbuf.getvalue()]))
示例#29
0
    def testCombinedTools(self):
        expectedResult = (ntou('Hello,world') +
                          europoundUnicode).encode('utf-8')
        zbuf = io.BytesIO()
        zfile = gzip.GzipFile(mode='wb', fileobj=zbuf, compresslevel=9)
        zfile.write(expectedResult)
        zfile.close()

        self.getPage('/euro',
                     headers=[('Accept-Encoding', 'gzip'),
                              ('Accept-Charset',
                               'ISO-8859-1,utf-8;q=0.7,*;q=0.7')])
        self.assertInBody(zbuf.getvalue()[:3])

        zbuf = io.BytesIO()
        zfile = gzip.GzipFile(mode='wb', fileobj=zbuf, compresslevel=6)
        zfile.write(expectedResult)
        zfile.close()

        self.getPage('/decorated_euro', headers=[('Accept-Encoding', 'gzip')])
        self.assertInBody(zbuf.getvalue()[:3])

        # This returns a different value because gzip's priority was
        # lowered in conf, allowing the rotator to run after gzip.
        # Of course, we don't want breakage in production apps,
        # but it proves the priority was changed.
        self.getPage('/decorated_euro/subpath',
                     headers=[('Accept-Encoding', 'gzip')])
        if six.PY3:
            self.assertInBody(bytes([(x + 3) % 256 for x in zbuf.getvalue()]))
        else:
            self.assertInBody(''.join(
                [chr((ord(x) + 3) % 256) for x in zbuf.getvalue()]))
示例#30
0
    def testMethodDispatch(self):
        self.getPage('/bymethod')
        self.assertBody("['another']")
        self.assertHeader('Allow', 'GET, HEAD, POST')

        self.getPage('/bymethod', method='HEAD')
        self.assertBody('')
        self.assertHeader('Allow', 'GET, HEAD, POST')

        self.getPage('/bymethod', method='POST', body='thing=one')
        self.assertBody('')
        self.assertHeader('Allow', 'GET, HEAD, POST')

        self.getPage('/bymethod')
        self.assertBody(repr(['another', ntou('one')]))
        self.assertHeader('Allow', 'GET, HEAD, POST')

        self.getPage('/bymethod', method='PUT')
        self.assertErrorPage(405)
        self.assertHeader('Allow', 'GET, HEAD, POST')

        # Test default with posparams
        self.getPage('/collection/silly', method='POST')
        self.getPage('/collection', method='GET')
        self.assertBody("['a', 'bit', 'silly']")

        # Test custom dispatcher set on app root (see #737).
        self.getPage('/app')
        self.assertBody('milk')
示例#31
0
    def testMethodDispatch(self):
        self.getPage("/bymethod")
        self.assertBody("['another']")
        self.assertHeader('Allow', 'GET, HEAD, POST')

        self.getPage("/bymethod", method="HEAD")
        self.assertBody("")
        self.assertHeader('Allow', 'GET, HEAD, POST')

        self.getPage("/bymethod", method="POST", body="thing=one")
        self.assertBody("")
        self.assertHeader('Allow', 'GET, HEAD, POST')

        self.getPage("/bymethod")
        self.assertBody(repr(['another', ntou('one')]))
        self.assertHeader('Allow', 'GET, HEAD, POST')

        self.getPage("/bymethod", method="PUT")
        self.assertErrorPage(405)
        self.assertHeader('Allow', 'GET, HEAD, POST')

        # Test default with posparams
        self.getPage("/collection/silly", method="POST")
        self.getPage("/collection", method="GET")
        self.assertBody("['a', 'bit', 'silly']")

        # Test custom dispatcher set on app root (see #737).
        self.getPage("/app")
        self.assertBody("milk")
示例#32
0
    def testCombinedTools(self):
        expectedResult = (ntou('Hello,world') +
                          europoundUnicode).encode('utf-8')
        zbuf = io.BytesIO()
        zfile = gzip.GzipFile(mode='wb', fileobj=zbuf, compresslevel=9)
        zfile.write(expectedResult)
        zfile.close()

        self.getPage('/euro',
                     headers=[
                         ('Accept-Encoding', 'gzip'),
                         ('Accept-Charset', 'ISO-8859-1,utf-8;q=0.7,*;q=0.7')])
        self.assertInBody(zbuf.getvalue()[:3])

        zbuf = io.BytesIO()
        zfile = gzip.GzipFile(mode='wb', fileobj=zbuf, compresslevel=6)
        zfile.write(expectedResult)
        zfile.close()

        self.getPage('/decorated_euro', headers=[('Accept-Encoding', 'gzip')])
        self.assertInBody(zbuf.getvalue()[:3])

        # This returns a different value because gzip's priority was
        # lowered in conf, allowing the rotator to run after gzip.
        # Of course, we don't want breakage in production apps,
        # but it proves the priority was changed.
        self.getPage('/decorated_euro/subpath',
                     headers=[('Accept-Encoding', 'gzip')])
        self.assertInBody(bytes([(x + 3) % 256 for x in zbuf.getvalue()]))
示例#33
0
def _old_process_multipart(entity):
    """The behavior of 3.2 and lower. Deprecated and will be changed in 3.3."""
    process_multipart(entity)

    params = entity.params

    for part in entity.parts:
        if part.name is None:
            key = ntou('parts')
        else:
            key = part.name

        if part.filename is None:
            # It's a regular field
            value = part.fullvalue()
        else:
            # It's a file upload. Retain the whole part so consumer code
            # has access to its .file and .filename attributes.
            value = part

        if key in params:
            if not isinstance(params[key], list):
                params[key] = [params[key]]
            params[key].append(value)
        else:
            params[key] = value
示例#34
0
def json_in(content_type=[ntou('application/json'),
                          ntou('text/javascript')],
            force=True,
            debug=False,
            processor=json_processor):
    """Add a processor to parse JSON request entities:
    The default processor places the parsed data into request.json.

    Incoming request entities which match the given content_type(s) will
    be deserialized from JSON to the Python equivalent, and the result
    stored at cherrypy.request.json. The 'content_type' argument may
    be a Content-Type string or a list of allowable Content-Type strings.

    If the 'force' argument is True (the default), then entities of other
    content types will not be allowed; "415 Unsupported Media Type" is
    raised instead.

    Supply your own processor to use a custom decoder, or to handle the parsed
    data differently.  The processor can be configured via
    tools.json_in.processor or via the decorator method.

    Note that the deserializer requires the client send a Content-Length
    request header, or it will raise "411 Length Required". If for any
    other reason the request entity cannot be deserialized from JSON,
    it will raise "400 Bad Request: Invalid JSON document".

    You must be using Python 2.6 or greater, or have the 'simplejson'
    package importable; otherwise, ValueError is raised during processing.
    """
    request = cherrypy.serving.request
    if isinstance(content_type, text_or_bytes):
        content_type = [content_type]

    if force:
        if debug:
            cherrypy.log(
                'Removing body processors %s' %
                repr(request.body.processors.keys()), 'TOOLS.JSON_IN')
        request.body.processors.clear()
        request.body.default_proc = cherrypy.HTTPError(
            415,
            'Expected an entity of content type %s' % ', '.join(content_type))

    for ct in content_type:
        if debug:
            cherrypy.log('Adding body processor for %s' % ct, 'TOOLS.JSON_IN')
        request.body.processors[ct] = processor
示例#35
0
def _check_unicode_filesystem(tmpdir):
    filename = tmpdir / ntou('☃', 'utf-8')
    tmpl = 'File system encoding ({encoding}) cannot support unicode filenames'
    msg = tmpl.format(encoding=sys.getfilesystemencoding())
    try:
        io.open(str(filename), 'w').close()
    except UnicodeEncodeError:
        pytest.skip(msg)
示例#36
0
def unicode_filesystem(tmpdir):
    filename = tmpdir / ntou('☃', 'utf-8')
    tmpl = 'File system encoding ({encoding}) cannot support unicode filenames'
    msg = tmpl.format(encoding=sys.getfilesystemencoding())
    try:
        io.open(str(filename), 'w').close()
    except UnicodeEncodeError:
        pytest.skip(msg)
示例#37
0
    def test_encoded_headers(self):
        # First, make sure the innards work like expected.
        self.assertEqual(httputil.decode_TEXT(ntou('=?utf-8?q?f=C3=BCr?=')),
                         ntou('f\xfcr'))

        if cherrypy.server.protocol_version == 'HTTP/1.1':
            # Test RFC-2047-encoded request and response header values
            u = ntou('\u212bngstr\xf6m', 'escape')
            c = ntou('=E2=84=ABngstr=C3=B6m')
            self.getPage('/headers/ifmatch',
                         [('If-Match', ntou('=?utf-8?q?%s?=') % c)])
            # The body should be utf-8 encoded.
            self.assertBody(ntob('\xe2\x84\xabngstr\xc3\xb6m'))
            # But the Etag header should be RFC-2047 encoded (binary)
            self.assertHeader('ETag', ntou('=?utf-8?b?4oSrbmdzdHLDtm0=?='))

            # Test a *LONG* RFC-2047-encoded request and response header value
            self.getPage('/headers/ifmatch',
                         [('If-Match', ntou('=?utf-8?q?%s?=') % (c * 10))])
            self.assertBody(ntob('\xe2\x84\xabngstr\xc3\xb6m') * 10)
            # Note: this is different output for Python3, but it decodes fine.
            etag = self.assertHeader(
                'ETag',
                '=?utf-8?b?4oSrbmdzdHLDtm3ihKtuZ3N0csO2beKEq25nc3Ryw7Zt'
                '4oSrbmdzdHLDtm3ihKtuZ3N0csO2beKEq25nc3Ryw7Zt'
                '4oSrbmdzdHLDtm3ihKtuZ3N0csO2beKEq25nc3Ryw7Zt'
                '4oSrbmdzdHLDtm0=?=')
            self.assertEqual(httputil.decode_TEXT(etag), u * 10)
    def test_encoded_headers(self):
        # First, make sure the innards work like expected.
        self.assertEqual(httputil.decode_TEXT(ntou("=?utf-8?q?f=C3=BCr?=")), ntou("f\xfcr"))

        if cherrypy.server.protocol_version == "HTTP/1.1":
            # Test RFC-2047-encoded request and response header values
            u = ntou('\u212bngstr\xf6m', 'escape')
            c = ntou("=E2=84=ABngstr=C3=B6m")
            self.getPage("/headers/ifmatch", [('If-Match', ntou('=?utf-8?q?%s?=') % c)])
            # The body should be utf-8 encoded.
            self.assertBody(ntob("\xe2\x84\xabngstr\xc3\xb6m"))
            # But the Etag header should be RFC-2047 encoded (binary)
            self.assertHeader("ETag", ntou('=?utf-8?b?4oSrbmdzdHLDtm0=?='))

            # Test a *LONG* RFC-2047-encoded request and response header value
            self.getPage("/headers/ifmatch",
                         [('If-Match', ntou('=?utf-8?q?%s?=') % (c * 10))])
            self.assertBody(ntob("\xe2\x84\xabngstr\xc3\xb6m") * 10)
            # Note: this is different output for Python3, but it decodes fine.
            etag = self.assertHeader("ETag",
                '=?utf-8?b?4oSrbmdzdHLDtm3ihKtuZ3N0csO2beKEq25nc3Ryw7Zt'
                '4oSrbmdzdHLDtm3ihKtuZ3N0csO2beKEq25nc3Ryw7Zt'
                '4oSrbmdzdHLDtm3ihKtuZ3N0csO2beKEq25nc3Ryw7Zt'
                '4oSrbmdzdHLDtm0=?=')
            self.assertEqual(httputil.decode_TEXT(etag), u * 10)
示例#39
0
 def __init__(self, environ, start_response, cpapp):
     if not py3k:
         if environ.get(ntou('wsgi.version')) == (ntou('u'), 0):
             environ = downgrade_wsgi_ux_to_1x(environ)
     self.environ = environ
     self.cpapp = cpapp
     try:
         self.run()
     except:
         self.close()
         raise
     r = _cherrypy.serving.response
     self.iter_response = iter(r.body)
     try:
         self.write = start_response(r.output_status, r.header_list)
     except:
         self.close()
         raise
示例#40
0
 def __init__(self, environ, start_response, cpapp):
     if not py3k:
         if environ.get(ntou('wsgi.version')) == (ntou('u'), 0):
             environ = downgrade_wsgi_ux_to_1x(environ)
     self.environ = environ
     self.cpapp = cpapp
     try:
         self.run()
     except:
         self.close()
         raise
     r = _cherrypy.serving.response
     self.iter_response = iter(r.body)
     try:
         self.write = start_response(r.output_status, r.header_list)
     except:
         self.close()
         raise
示例#41
0
    def testParams(self):
        self.getPage("/params/?thing=a")
        self.assertBody(repr(ntou("a")))

        self.getPage("/params/?thing=a&thing=b&thing=c")
        self.assertBody(repr([ntou('a'), ntou('b'), ntou('c')]))

        # Test friendly error message when given params are not accepted.
        cherrypy.config.update({"request.show_mismatched_params": True})
        self.getPage("/params/?notathing=meeting")
        self.assertInBody("Missing parameters: thing")
        self.getPage("/params/?thing=meeting&notathing=meeting")
        self.assertInBody("Unexpected query string parameters: notathing")

        # Test ability to turn off friendly error messages
        cherrypy.config.update({"request.show_mismatched_params": False})
        self.getPage("/params/?notathing=meeting")
        self.assertInBody("Not Found")
        self.getPage("/params/?thing=meeting&notathing=meeting")
        self.assertInBody("Not Found")

        # Test "% HEX HEX"-encoded URL, param keys, and values
        self.getPage("/params/%d4%20%e3/cheese?Gruy%E8re=Bulgn%e9ville")
        self.assertBody("args: %s kwargs: %s" %
                        (('\xd4 \xe3', 'cheese'),
                         [('Gruy\xe8re', ntou('Bulgn\xe9ville'))]))

        # Make sure that encoded = and & get parsed correctly
        self.getPage(
            "/params/code?url=http%3A//cherrypy.org/index%3Fa%3D1%26b%3D2")
        self.assertBody("args: %s kwargs: %s" %
                        (('code',),
                         [('url', ntou('http://cherrypy.org/index?a=1&b=2'))]))

        # Test coordinates sent by <img ismap>
        self.getPage("/params/ismap?223,114")
        self.assertBody("Coordinates: 223, 114")

        # Test "name[key]" dict-like params
        self.getPage("/params/dictlike?a[1]=1&a[2]=2&b=foo&b[bar]=baz")
        self.assertBody("args: %s kwargs: %s" %
                        (('dictlike',),
                         [('a[1]', ntou('1')), ('a[2]', ntou('2')),
                          ('b', ntou('foo')), ('b[bar]', ntou('baz'))]))
示例#42
0
文件: _cptree.py 项目: Pluckyduck/eve
 def __call__(self, environ, start_response):
     env1x = environ
     if environ.get(ntou('wsgi.version')) == (ntou('u'), 0):
         env1x = _cpwsgi.downgrade_wsgi_ux_to_1x(environ)
     path = httputil.urljoin(env1x.get('SCRIPT_NAME', ''), env1x.get('PATH_INFO', ''))
     sn = self.script_name(path or '/')
     if sn is None:
         start_response('404 Not Found', [])
         return []
     app = self.apps[sn]
     environ = environ.copy()
     if environ.get(u'wsgi.version') == (u'u', 0):
         enc = environ[u'wsgi.url_encoding']
         environ[u'SCRIPT_NAME'] = sn.decode(enc)
         environ[u'PATH_INFO'] = path[len(sn.rstrip('/')):].decode(enc)
     else:
         environ['SCRIPT_NAME'] = sn
         environ['PATH_INFO'] = path[len(sn.rstrip('/')):]
     return app(environ, start_response)
示例#43
0
 def __call__(self, environ, start_response):
     env1x = environ
     if environ.get(ntou('wsgi.version')) == (ntou('u'), 0):
         env1x = _cpwsgi.downgrade_wsgi_ux_to_1x(environ)
     path = httputil.urljoin(env1x.get('SCRIPT_NAME', ''), env1x.get('PATH_INFO', ''))
     sn = self.script_name(path or '/')
     if sn is None:
         start_response('404 Not Found', [])
         return []
     app = self.apps[sn]
     environ = environ.copy()
     if environ.get(u'wsgi.version') == (u'u', 0):
         enc = environ[u'wsgi.url_encoding']
         environ[u'SCRIPT_NAME'] = sn.decode(enc)
         environ[u'PATH_INFO'] = path[len(sn.rstrip('/')):].decode(enc)
     else:
         environ['SCRIPT_NAME'] = sn
         environ['PATH_INFO'] = path[len(sn.rstrip('/')):]
     return app(environ, start_response)
示例#44
0
文件: _cpwsgi.py 项目: coady/cherrypy
    def __init__(self, environ, start_response, cpapp):
        self.cpapp = cpapp
        try:
            if six.PY2:
                if environ.get(ntou('wsgi.version')) == (ntou('u'), 0):
                    environ = downgrade_wsgi_ux_to_1x(environ)
            self.environ = environ
            self.run()

            r = _cherrypy.serving.response

            outstatus = r.output_status
            if not isinstance(outstatus, bytes):
                raise TypeError('response.output_status is not a byte string.')

            outheaders = []
            for k, v in r.header_list:
                if not isinstance(k, bytes):
                    tmpl = 'response.header_list key %r is not a byte string.'
                    raise TypeError(tmpl % k)
                if not isinstance(v, bytes):
                    tmpl = (
                        'response.header_list value %r is not a byte string.'
                    )
                    raise TypeError(tmpl % v)
                outheaders.append((k, v))

            if six.PY3:
                # According to PEP 3333, when using Python 3, the response
                # status and headers must be bytes masquerading as unicode;
                # that is, they must be of type "str" but are restricted to
                # code points in the "latin-1" set.
                outstatus = outstatus.decode('ISO-8859-1')
                outheaders = [
                    (k.decode('ISO-8859-1'), v.decode('ISO-8859-1'))
                    for k, v in outheaders
                ]

            self.iter_response = iter(r.body)
            self.write = start_response(outstatus, outheaders)
        except BaseException:
            self.close()
            raise
示例#45
0
    def __init__(self, environ, start_response, cpapp):
        self.cpapp = cpapp
        try:
            if six.PY2:
                if environ.get(ntou('wsgi.version')) == (ntou('u'), 0):
                    environ = downgrade_wsgi_ux_to_1x(environ)
            self.environ = environ
            self.run()

            r = _cherrypy.serving.response

            outstatus = r.output_status
            if not isinstance(outstatus, bytes):
                raise TypeError('response.output_status is not a byte string.')

            outheaders = []
            for k, v in r.header_list:
                if not isinstance(k, bytes):
                    tmpl = 'response.header_list key %r is not a byte string.'
                    raise TypeError(tmpl % k)
                if not isinstance(v, bytes):
                    tmpl = (
                        'response.header_list value %r is not a byte string.'
                    )
                    raise TypeError(tmpl % v)
                outheaders.append((k, v))

            if six.PY3:
                # According to PEP 3333, when using Python 3, the response
                # status and headers must be bytes masquerading as unicode;
                # that is, they must be of type "str" but are restricted to
                # code points in the "latin-1" set.
                outstatus = outstatus.decode('ISO-8859-1')
                outheaders = [
                    (k.decode('ISO-8859-1'), v.decode('ISO-8859-1'))
                    for k, v in outheaders
                ]

            self.iter_response = iter(r.body)
            self.write = start_response(outstatus, outheaders)
        except BaseException:
            self.close()
            raise
示例#46
0
def json_in(content_type=[ntou('application/json'), ntou('text/javascript')],
            force=True, debug=False, processor = json_processor):
    """Add a processor to parse JSON request entities:
    The default processor places the parsed data into request.json.

    Incoming request entities which match the given content_type(s) will
    be deserialized from JSON to the Python equivalent, and the result
    stored at cherrypy.request.json. The 'content_type' argument may
    be a Content-Type string or a list of allowable Content-Type strings.

    If the 'force' argument is True (the default), then entities of other
    content types will not be allowed; "415 Unsupported Media Type" is
    raised instead.

    Supply your own processor to use a custom decoder, or to handle the parsed
    data differently.  The processor can be configured via
    tools.json_in.processor or via the decorator method.

    Note that the deserializer requires the client send a Content-Length
    request header, or it will raise "411 Length Required". If for any
    other reason the request entity cannot be deserialized from JSON,
    it will raise "400 Bad Request: Invalid JSON document".

    You must be using Python 2.6 or greater, or have the 'simplejson'
    package importable; otherwise, ValueError is raised during processing.
    """
    request = cherrypy.serving.request
    if isinstance(content_type, basestring):
        content_type = [content_type]

    if force:
        if debug:
            cherrypy.log('Removing body processors %s' %
                         repr(request.body.processors.keys()), 'TOOLS.JSON_IN')
        request.body.processors.clear()
        request.body.default_proc = cherrypy.HTTPError(
            415, 'Expected an entity of content type %s' %
            ', '.join(content_type))

    for ct in content_type:
        if debug:
            cherrypy.log('Adding body processor for %s' % ct, 'TOOLS.JSON_IN')
        request.body.processors[ct] = processor
def decompress_json(entity):
    """Try decompressing json before parsing, incase compressed
    content was sent to the server"""

    if not entity.headers.get(ntou("Content-Length"), ntou("")):
        raise cherrypy.HTTPError(411)
    
    body = entity.fp.read()
    # decompress if gzip content type
    if entity.headers.get(ntou("Content-Type")) == ntou("application/gzip"):
        try:
            body = zlib.decompress(body)
        except:
            raise cherrypy.HTTPError(500, 'Invalid gzip data')

    try:
        cherrypy.serving.request.json = json_decode(body.decode('utf-8'))
    except ValueError:
        raise cherrypy.HTTPError(400, 'Invalid JSON document')
def decompress_json(entity):
    """Try decompressing json before parsing, incase compressed
    content was sent to the server"""

    if not entity.headers.get(ntou("Content-Length"), ntou("")):
        raise cherrypy.HTTPError(411)

    body = entity.fp.read()
    # decompress if gzip content type
    if entity.headers.get(ntou("Content-Type")) == ntou("application/gzip"):
        try:
            body = zlib.decompress(body)
        except:
            raise cherrypy.HTTPError(500, 'Invalid gzip data')

    try:
        cherrypy.serving.request.json = json_decode(body.decode('utf-8'))
    except ValueError:
        raise cherrypy.HTTPError(400, 'Invalid JSON document')
示例#49
0
def json_processor(entity):
    """
    Read application/json data into the request arguments.

    This is am almost identical copy of the CherryPy JSON tool's
    json_processor() with the only difference that this version merges any json
    data decoded from the body, into the request arguments instead of the
    request.json object.

    This makes JSON and normal form input data completely indistinguishable
    fvrom each other as far as the request handlers go.
    """
    if not entity.headers.get(ntou("Content-Length"), ntou("")):
        raise cherrypy.HTTPError(411)

    body = entity.fp.read()
    try:
        cherrypy.serving.request.params.update(json_decode(body.decode('utf-8')))
    except ValueError:
        raise cherrypy.HTTPError(400, 'Invalid JSON document')
示例#50
0
 def test_redirect_with_unicode(self):
     """
     A redirect to a URL with Unicode should return a Location
     header containing that Unicode URL.
     """
     # test disabled due to #1440
     return
     self.getPage('/redirect/url_with_unicode')
     self.assertStatus(303)
     loc = self.assertHeader('Location')
     assert ntou('тест', encoding='utf-8') in loc
示例#51
0
 def test_redirect_with_unicode(self):
     """
     A redirect to a URL with Unicode should return a Location
     header containing that Unicode URL.
     """
     # test disabled due to #1440
     return
     self.getPage("/redirect/url_with_unicode")
     self.assertStatus(303)
     loc = self.assertHeader('Location')
     assert ntou('тест', encoding='utf-8') in loc
示例#52
0
def json_in(content_type=[ntou('application/json'),
                          ntou('text/javascript')],
            force=True,
            debug=False,
            processor=json_processor):
    request = cherrypy.serving.request
    if isinstance(content_type, basestring):
        content_type = [content_type]
    if force:
        if debug:
            cherrypy.log(
                'Removing body processors %s' %
                repr(request.body.processors.keys()), 'TOOLS.JSON_IN')
        request.body.processors.clear()
        request.body.default_proc = cherrypy.HTTPError(
            415,
            'Expected an entity of content type %s' % ', '.join(content_type))
    for ct in content_type:
        if debug:
            cherrypy.log('Adding body processor for %s' % ct, 'TOOLS.JSON_IN')
        request.body.processors[ct] = processor
示例#53
0
def zlib_processor(
        entity):  # pragma: no cover, not used in the testing environment...
    """Read application/zlib data and put content into entity.params for later use.

    :param entity: cherrypy entity
    :type entity: cherrypy._cpreqbody.Entity
    :return: None
    """
    if not entity.headers.get(ntou("Content-Length"), ntou("")):
        raise cherrypy.HTTPError(411)

    body = entity.fp.read()
    try:
        body = zlib.decompress(body)
    except zlib.error:
        raise cherrypy.HTTPError(400, 'Invalid zlib data')
    try:
        raw_params = json.loads(body)
    except ValueError:
        raise cherrypy.HTTPError(400, 'Invalid JSON document in zlib data')

    try:
        params = {}
        for key, value in list(raw_params.items()):
            params[key] = unserialize(value.encode("utf8"))
    except TypeError:
        raise cherrypy.HTTPError(400,
                                 'Invalid serialized data in JSON document')
    except AlignakClassLookupException as exp:
        cherrypy.HTTPError(400, 'Cannot un-serialize data received: %s' % exp)

    # Now that all values have been successfully parsed and decoded,
    # apply them to the entity.params dict.
    for key, value in list(params.items()):
        if key in entity.params:
            if not isinstance(entity.params[key], list):
                entity.params[key] = [entity.params[key]]
            entity.params[key].append(value)
        else:
            entity.params[key] = value
def zlib_processor(entity):  # pragma: no cover, not used in the testing environment...
    """Read application/zlib data and put content into entity.params for later use.

    :param entity: cherrypy entity
    :type entity: cherrypy._cpreqbody.Entity
    :return: None
    """
    if not entity.headers.get(ntou("Content-Length"), ntou("")):
        raise cherrypy.HTTPError(411)

    body = entity.fp.read()
    try:
        body = zlib.decompress(body)
    except zlib.error:
        raise cherrypy.HTTPError(400, 'Invalid zlib data')
    try:
        raw_params = json.loads(body)
    except ValueError:
        raise cherrypy.HTTPError(400, 'Invalid JSON document in zlib data')

    try:
        params = {}
        for key, value in list(raw_params.items()):
            params[key] = unserialize(value.encode("utf8"))
    except TypeError:
        raise cherrypy.HTTPError(400, 'Invalid serialized data in JSON document')
    except AlignakClassLookupException as exp:
        cherrypy.HTTPError(400, 'Cannot un-serialize data received: %s' % exp)

    # Now that all values have been successfully parsed and decoded,
    # apply them to the entity.params dict.
    for key, value in list(params.items()):
        if key in entity.params:
            if not isinstance(entity.params[key], list):
                entity.params[key] = [entity.params[key]]
            entity.params[key].append(value)
        else:
            entity.params[key] = value
示例#55
0
def zlib_processor(entity):
    """Read application/zlib data and put content into entity.params for later use.

    :param entity: cherrypy entity
    :type entity: cherrypy._cpreqbody.Entity
    :return: None
    """
    if not entity.headers.get(ntou("Content-Length"), ntou("")):
        raise cherrypy.HTTPError(411)

    body = entity.fp.read()
    try:
        body = zlib.decompress(body)
    except zlib.error:
        raise cherrypy.HTTPError(400, 'Invalid zlib data')
    try:
        raw_params = json.loads(body)
    except ValueError:
        raise cherrypy.HTTPError(400, 'Invalid JSON document in zlib data')

    try:
        params = {}
        for key, value in raw_params.iteritems():
            params[key] = cPickle.loads(value.encode("utf8"))
    except TypeError:
        raise cherrypy.HTTPError(400, 'Invalid Pickle data in JSON document')

    # Now that all values have been successfully parsed and decoded,
    # apply them to the entity.params dict.
    for key, value in params.items():
        if key in entity.params:
            if not isinstance(entity.params[key], list):
                entity.params[key] = [entity.params[key]]
            entity.params[key].append(value)
        else:
            entity.params[key] = value
示例#56
0
 def testCombinedTools(self):
     expectedResult = (ntou('Hello,world') + europoundUnicode).encode('utf-8')
     zbuf = BytesIO()
     zfile = gzip.GzipFile(mode='wb', fileobj=zbuf, compresslevel=9)
     zfile.write(expectedResult)
     zfile.close()
     self.getPage('/euro', headers=[('Accept-Encoding', 'gzip'), ('Accept-Charset', 'ISO-8859-1,utf-8;q=0.7,*;q=0.7')])
     self.assertInBody(zbuf.getvalue()[:3])
     zbuf = BytesIO()
     zfile = gzip.GzipFile(mode='wb', fileobj=zbuf, compresslevel=6)
     zfile.write(expectedResult)
     zfile.close()
     self.getPage('/decorated_euro', headers=[('Accept-Encoding', 'gzip')])
     self.assertInBody(zbuf.getvalue()[:3])
     self.getPage('/decorated_euro/subpath', headers=[('Accept-Encoding', 'gzip')])
     self.assertInBody(''.join([ chr((ord(x) + 3) % 256) for x in zbuf.getvalue() ]))