Esempio n. 1
0
def generate_formdata(req, resp, params):
    """sets prarams['form'] to pass to every endpoint.
    """
    #print "here"
    form = dict()
    files = dict()
    if req.method == 'GET':
        di = parse_query_string(req.query_string)
        form = dict(di)
        params['form'], params['files'] = dict(form), dict(files)
    else:
        if 'json' in req.get_header('content-type', None):
            form = json.load(req.stream)
            params['form'], params['files'] = dict(form), dict(files)
        else:
            mimetype, options = parse_options_header(req.get_header('content-type'))
            data = req.stream.read()
            environ = {'wsgi.input': StringIO(data),
                       'CONTENT_LENGTH': str(len(data)),
                       'CONTENT_TYPE': req.get_header('content-type'),
                       'REQUEST_METHOD': 'POST'}
            stream, tempform, tempfiles = parse_form_data(environ)
            for item in tempform:
                form[item] = tempform[item]
            di = parse_query_string(req.query_string)
            for item in di:
                form[item] = di[item]
            for item in tempfiles:
                files[item] = tempfiles[item]
            params['form'], params['files'] = dict(form), dict(files)
    return True
Esempio n. 2
0
    def test_parse_query_string(self):
        query_strinq = (
            'a=http%3A%2F%2Ffalconframework.org%3Ftest%3D1'
            '&b=%7B%22test1%22%3A%20%22data1%22%'
            '2C%20%22test2%22%3A%20%22data2%22%7D'
            '&c=1,2,3'
            '&d=test'
            '&e=a,,%26%3D%2C'
            '&f=a&f=a%3Db'
            '&%C3%A9=a%3Db'
        )
        decoded_url = 'http://falconframework.org?test=1'
        decoded_json = '{"test1": "data1", "test2": "data2"}'

        result = uri.parse_query_string(query_strinq)
        assert result['a'] == decoded_url
        assert result['b'] == decoded_json
        assert result['c'] == ['1', '2', '3']
        assert result['d'] == 'test'
        assert result['e'] == ['a', '&=,']
        assert result['f'] == ['a', 'a=b']
        assert result['é'] == 'a=b'

        result = uri.parse_query_string(query_strinq, True)
        assert result['a'] == decoded_url
        assert result['b'] == decoded_json
        assert result['c'] == ['1', '2', '3']
        assert result['d'] == 'test'
        assert result['e'] == ['a', '', '&=,']
        assert result['f'] == ['a', 'a=b']
        assert result['é'] == 'a=b'
Esempio n. 3
0
    def test_parse_query_string(self):
        query_strinq = ("a=http%3A%2F%2Ffalconframework.org%3Ftest%3D1"
                        "&b=%7B%22test1%22%3A%20%22data1%22%"
                        "2C%20%22test2%22%3A%20%22data2%22%7D"
                        "&c=1,2,3"
                        "&d=test"
                        "&e=a,,%26%3D%2C"
                        "&f=a&f=a%3Db"
                        "&%C3%A9=a%3Db")
        decoded_url = 'http://falconframework.org?test=1'
        decoded_json = '{"test1": "data1", "test2": "data2"}'

        result = uri.parse_query_string(query_strinq)
        self.assertEqual(result['a'], decoded_url)
        self.assertEqual(result['b'], decoded_json)
        self.assertEqual(result['c'], ['1', '2', '3'])
        self.assertEqual(result['d'], 'test')
        self.assertEqual(result['e'], ['a', '&=,'])
        self.assertEqual(result['f'], ['a', 'a=b'])
        self.assertEqual(result[u'é'], 'a=b')

        result = uri.parse_query_string(query_strinq, True)
        self.assertEqual(result['a'], decoded_url)
        self.assertEqual(result['b'], decoded_json)
        self.assertEqual(result['c'], ['1', '2', '3'])
        self.assertEqual(result['d'], 'test')
        self.assertEqual(result['e'], ['a', '', '&=,'])
        self.assertEqual(result['f'], ['a', 'a=b'])
        self.assertEqual(result[u'é'], 'a=b')
Esempio n. 4
0
    def test_parse_query_string(self):
        query_strinq = (
            "a=http%3A%2F%2Ffalconframework.org%3Ftest%3D1"
            "&b=%7B%22test1%22%3A%20%22data1%22%"
            "2C%20%22test2%22%3A%20%22data2%22%7D"
            "&c=1,2,3"
            "&d=test"
            "&e=a,,%26%3D%2C"
            "&f=a&f=a%3Db"
            "&%C3%A9=a%3Db"
        )
        decoded_url = 'http://falconframework.org?test=1'
        decoded_json = '{"test1": "data1", "test2": "data2"}'

        result = uri.parse_query_string(query_strinq)
        self.assertEqual(result['a'], decoded_url)
        self.assertEqual(result['b'], decoded_json)
        self.assertEqual(result['c'], ['1', '2', '3'])
        self.assertEqual(result['d'], 'test')
        self.assertEqual(result['e'], ['a', '&=,'])
        self.assertEqual(result['f'], ['a', 'a=b'])
        self.assertEqual(result[u'é'], 'a=b')

        result = uri.parse_query_string(query_strinq, True)
        self.assertEqual(result['a'], decoded_url)
        self.assertEqual(result['b'], decoded_json)
        self.assertEqual(result['c'], ['1', '2', '3'])
        self.assertEqual(result['d'], 'test')
        self.assertEqual(result['e'], ['a', '', '&=,'])
        self.assertEqual(result['f'], ['a', 'a=b'])
        self.assertEqual(result[u'é'], 'a=b')
Esempio n. 5
0
    def test_parse_query_string(self):
        query_string = ('a=http%3A%2F%2Ffalconframework.org%3Ftest%3D1'
                        '&b=%7B%22test1%22%3A%20%22data1%22%'
                        '2C%20%22test2%22%3A%20%22data2%22%7D'
                        '&c=1,2,3'
                        '&d=test'
                        '&e=a,,%26%3D%2C'
                        '&f=a&f=a%3Db'
                        '&%C3%A9=a%3Db')
        decoded_url = 'http://falconframework.org?test=1'
        decoded_json = '{"test1": "data1", "test2": "data2"}'

        result = uri.parse_query_string(query_string)
        assert result['a'] == decoded_url
        assert result['b'] == decoded_json
        assert result['c'] == ['1', '2', '3']
        assert result['d'] == 'test'
        assert result['e'] == ['a', '&=,']
        assert result['f'] == ['a', 'a=b']
        assert result['é'] == 'a=b'

        result = uri.parse_query_string(query_string, True)
        assert result['a'] == decoded_url
        assert result['b'] == decoded_json
        assert result['c'] == ['1', '2', '3']
        assert result['d'] == 'test'
        assert result['e'] == ['a', '', '&=,']
        assert result['f'] == ['a', 'a=b']
        assert result['é'] == 'a=b'
Esempio n. 6
0
def generate_formdata(req, resp, params):
    form = dict()
    files = dict()
    if req.method == 'GET':
        di = parse_query_string(req.query_string)
        form = dict(di)
        params['form'], params['files'] = dict(form), dict(files)
    else:
        if 'json' in req.get_header('content-type', None):
            #if the method type is post "form" variable below can contain 
            #only either the post body or the quer parameter at once, modify 
            #umcomment the below commented line to store query parameters in "form"
            form = json.load(req.stream)
            #form = dict(parse_query_string(req.query_string))
            params['form'], params['files'] = dict(form), dict(files)
        else:
            mimetype, options = parse_options_header(req.get_header('content-type'))
            data = req.stream.read()
            environ = {'wsgi.input':StringIO(data),
                       'CONTENT_LENGTH': str(len(data)),
                       'CONTENT_TYPE': req.get_header('content-type'),
                       'REQUEST_METHOD': 'POST'}
            stream, tempform, tempfiles = parse_form_data(environ)
            for item in tempform:
                form[item] = tempform[item]
            di = parse_query_string(req.query_string)
            for item in di:
                form[item] = di[item]
            for item in tempfiles:
                files[item] = tempfiles[item]
            params['form'], params['files'] = dict(form), dict(files)
    #print form
    #print params
    return True
Esempio n. 7
0
    def on_post(self, request, response):
        body = request.stream.read()
        encoded_raw_post_data = self.parse_request_data(body)

        pretty = request.get_param("pretty")
        if not pretty:
            pretty = parse_query_string(encoded_raw_post_data).get("pretty", False)

        data = request.get_param("data")
        if not data:
            data = parse_query_string(encoded_raw_post_data).get("data", False)
            if not data:
                data = encoded_raw_post_data

        if not data:
            return {"error": "No data posted or data incorrectly encoded"}

        action_str = request.get_param("action")
        if not action_str:
            action_str = parse_query_string(encoded_raw_post_data).get("action", None)

        if not action_str or action_str not in ACTIONS:
            action_str = "pos_tagging"

        action = ACTIONS[action_str]()
        tagged_json = action.parse(data)

        json_kwargs = {"separators": (',', ':')}
        if pretty:
            json_kwargs = {"indent": 4, "separators": (', ', ': ')}

        response.body = json.dumps(tagged_json, **json_kwargs)
Esempio n. 8
0
    def test_parse_query_string(self):
        query_strinq = (
            "a=http%3A%2F%2Ffalconframework.org%3Ftest%3D1"
            "&b=%7B%22test1%22%3A%20%22data1%22%"
            "2C%20%22test2%22%3A%20%22data2%22%7D"
            "&c=1,2,3"
            "&d=test"
            "&e=a,,%26%3D%2C"
            "&f=a&f=a%3Db"
            "&%C3%A9=a%3Db"
        )
        decoded_url = "http://falconframework.org?test=1"
        decoded_json = '{"test1": "data1", "test2": "data2"}'

        result = uri.parse_query_string(query_strinq)
        self.assertEqual(result["a"], decoded_url)
        self.assertEqual(result["b"], decoded_json)
        self.assertEqual(result["c"], ["1", "2", "3"])
        self.assertEqual(result["d"], "test")
        self.assertEqual(result["e"], ["a", "&=,"])
        self.assertEqual(result["f"], ["a", "a=b"])
        self.assertEqual(result[u"é"], "a=b")

        result = uri.parse_query_string(query_strinq, True)
        self.assertEqual(result["a"], decoded_url)
        self.assertEqual(result["b"], decoded_json)
        self.assertEqual(result["c"], ["1", "2", "3"])
        self.assertEqual(result["d"], "test")
        self.assertEqual(result["e"], ["a", "", "&=,"])
        self.assertEqual(result["f"], ["a", "a=b"])
        self.assertEqual(result[u"é"], "a=b")
Esempio n. 9
0
    def _parse_form_urlencoded(self):
        content_length = self.content_length
        if not content_length:
            return

        body = self.stream.read(content_length)

        # NOTE(kgriffs): According to http://goo.gl/6rlcux the
        # body should be US-ASCII. Enforcing this also helps
        # catch malicious input.
        try:
            body = body.decode('ascii')
        except UnicodeDecodeError:
            body = None
            self.log_error('Non-ASCII characters found in form body '
                           'with Content-Type of '
                           'application/x-www-form-urlencoded. Body '
                           'will be ignored.')

        if body:
            extra_params = parse_query_string(
                body,
                keep_blank_qs_values=self.options.keep_blank_qs_values,
                parse_qs_csv=self.options.auto_parse_qs_csv,
            )

            self._params.update(extra_params)
Esempio n. 10
0
    def on_post(self, req, resp):
        form_body = uri.parse_query_string(req.context['body'])

        try:
            username = form_body['username']
            password = form_body['password']
        except KeyError:
            raise HTTPFound('/login')

        if not auth.valid_username(username):
            logger.warn('Tried to login with invalid username %s', username)
            if self.debug:
                flash_message(req, 'Invalid username', 'danger')
            else:
                flash_message(req, 'Invalid credentials', 'danger')
            raise HTTPFound('/login')

        if self.auth_manager.authenticate(username, password):
            logger.info('Successful login for %s', username)
            auth.login_user(req, username)
        else:
            logger.warn('Failed login for %s', username)
            flash_message(req, 'Invalid credentials', 'danger')
            raise HTTPFound('/login')

        # Remove newlines to prevent HTTP request splitting
        url = req.get_param('next', default='').replace('\n', '')

        if not url or url.startswith('/'):
            raise HTTPFound(url or default_route)
        else:
            raise HTTPBadRequest('Invalid next parameter', '')
Esempio n. 11
0
    def on_get(self, req, resp, id=None, offset=0, limit=200):
        """Get all subscribers if no query args. If email in query args
        then return subscriber matching email. If id in route return that
        object."""
        args = parse_query_string(req.query_string)
        email = args.get('email', None)
        if args.get('limit'):
            try:
                limit = int(args.get('limit'))
                if limit > 200:
                    raise ValueError('Limit can not exceed 200')
            except ValueError as e:
                raise HTTPBadRequest('Invalid value for limit', e.message)

        if args.get('offset'):
            try:
                offset = int(args.get('offset'))
            except ValueError as e:
                raise HTTPBadRequest('Invalid value for limit', e.message)

        try:
            rdb = RethinkDBClient()
            if id:
                resp.body = rdb.get(self._table_name, 'id', id)
            elif email:
                resp.body = rdb.get(self._table_name, 'email', email)
            elif limit:
                resp.body = rdb.get_all(self._table_name, offset * limit,
                                        limit)
            else:
                resp.status = HTTP_400
                resp.body = bad_request(info='Invalid request')
        except RqlError as e:
            raise HTTPBadRequest('Invalid request', e.message)
Esempio n. 12
0
    def _parse_form_urlencoded(self):
        # NOTE(kgriffs): This assumes self.stream has been patched
        # above in the case of wsgiref, so that self.content_length
        # is not needed. Normally we just avoid accessing
        # self.content_length, because it is a little expensive
        # to call. We could cache self.content_length, but the
        # overhead to do that won't usually be helpful, since
        # content length will only ever be read once per
        # request in most cases.
        body = self.stream.read()

        # NOTE(kgriffs): According to http://goo.gl/6rlcux the
        # body should be US-ASCII. Enforcing this also helps
        # catch malicious input.
        try:
            body = body.decode('ascii')
        except UnicodeDecodeError:
            body = None
            self.log_error('Non-ASCII characters found in form body '
                           'with Content-Type of '
                           'application/x-www-form-urlencoded. Body '
                           'will be ignored.')

        if body:
            extra_params = parse_query_string(
                body,
                keep_blank_qs_values=self.options.keep_blank_qs_values,
                parse_qs_csv=self.options.auto_parse_qs_csv,
            )

            self._params.update(extra_params)
Esempio n. 13
0
    def _parse_form_urlencoded(self):
        content_length = self.content_length
        if not content_length:
            return

        body = self.stream.read(content_length)

        # NOTE(kgriffs): According to http://goo.gl/6rlcux the
        # body should be US-ASCII. Enforcing this also helps
        # catch malicious input.
        try:
            body = body.decode('ascii')
        except UnicodeDecodeError:
            body = None
            self.log_error('Non-ASCII characters found in form body '
                           'with Content-Type of '
                           'application/x-www-form-urlencoded. Body '
                           'will be ignored.')

        if body:
            extra_params = parse_query_string(
                body,
                keep_blank_qs_values=self.options.keep_blank_qs_values,
                parse_qs_csv=self.options.auto_parse_qs_csv,
            )

            self._params.update(extra_params)
Esempio n. 14
0
    def _parse_form_urlencoded(self):
        # NOTE(kgriffs): This assumes self.stream has been patched
        # above in the case of wsgiref, so that self.content_length
        # is not needed. Normally we just avoid accessing
        # self.content_length, because it is a little expensive
        # to call. We could cache self.content_length, but the
        # overhead to do that won't usually be helpful, since
        # content length will only ever be read once per
        # request in most cases.
        body = self.stream.read()

        # NOTE(kgriffs): According to http://goo.gl/6rlcux the
        # body should be US-ASCII. Enforcing this also helps
        # catch malicious input.
        try:
            body = body.decode("ascii")
        except UnicodeDecodeError:
            body = None
            self.log_error(
                "Non-ASCII characters found in form body "
                "with Content-Type of "
                "application/x-www-form-urlencoded. Body "
                "will be ignored."
            )

        if body:
            extra_params = parse_query_string(body, keep_blank_qs_values=self.options.keep_blank_qs_values)

            self._params.update(extra_params)
Esempio n. 15
0
    def process_resource(self, req, resp, resource, params):
        """
        :param req: Falcon request
        :type req: falcon.request.Request

        :param resp: Falcon response
        :type resp: falcon.response.Response

        :param resource:
        :type resource: falcon_dbapi.resources.base.BaseCollectionResource|
                        falcon_dbapi.resources.base.BaseSingleResource

        :param params: parameters dict
        :type params: dict
        """
        if resource is None or req.method not in ['POST', 'PUT', 'PATCH']:
            return

        body = req.stream.read()
        if not body:
            raise falcon.HTTPBadRequest('Empty request body', 'At least one value is required')
        try:
            body = body.decode('utf-8')
        except UnicodeDecodeError:
            raise falcon.HTTPBadRequest('Invalid request body', 'A valid UTF-8 encoded document is required')

        req.context['doc'] = parse_query_string(body, keep_blank_qs_values=True, parse_qs_csv=False)
Esempio n. 16
0
def on_post(req, resp):
    login_info = uri.parse_query_string(req.context['body'])

    user = login_info.get('username')
    password = login_info.get('password')
    if user is None or password is None:
        raise HTTPBadRequest('Invalid login attempt', 'Missing user/password')

    if not auth_manager.authenticate(user, password):
        raise HTTPUnauthorized('Authentication failure',
                               'bad login credentials', '')

    connection = db.connect()
    cursor = connection.cursor(db.DictCursor)
    data = get_user_data(None, {'name': user}, dbinfo=(connection, cursor))
    if not data:
        cursor.close()
        connection.close()
        raise HTTPNotFound()

    session = req.env['beaker.session']
    session['user'] = user
    session.save()
    csrf_token = '%x' % SystemRandom().getrandbits(128)
    cursor.execute(
        'INSERT INTO `session` (`id`, `csrf_token`) VALUES (%s, %s)',
        (req.env['beaker.session']['_id'], csrf_token))
    connection.commit()
    cursor.close()
    connection.close()

    # TODO: purge out of date csrf token
    data[0]['csrf_token'] = csrf_token
    resp.body = dumps(data[0])
Esempio n. 17
0
    def on_get(self, req, resp):
        args = parse_query_string(req.query_string)
        image_urls = {}
        try:
            # request access token
            code = args.get('code')
            url = '{0}?{1}={2}&{3}={4}&{5}={6}&{7}={8}&{9}={10}'.format(
                CONFIG['access_token_url'], 'client_id', CONFIG['access_key'],
                'client_secret', CONFIG['secret_key'], 'redirect_uri',
                'http://localhost:8000/callback', 'code', code, 'grant_type',
                'authorization_code')
            q = requests.post(url)

            # Save access token
            access_token = q.json().get('access_token', None)
            CACHE.set('access_token', access_token)

            # TODO: Use proper query string
            url = '{0}?{1}={2}&{3}={4}'.format(CONFIG['random_photo_url'],
                                               'query',
                                               list(get_conditions())[0],
                                               'orientation', 'landscape')
            q = requests.get(
                url,
                headers={'Authorization': 'Bearer {0}'.format(access_token)})
            print(q.status_code)
            print(q.content)
            print(q.json()['urls'])
            if q.status_code == 200:
                image_urls = q.json()['urls']
                resp.status = falcon.HTTP_200
                resp.body = json.dumps(image_urls)
        except Exception as exc:
            traceback.print_exc()
Esempio n. 18
0
    def _parse_form_urlencoded(self):
        # PERF(kgriffs): Technically, we should spend a few more
        # cycles and parse the content type for real, but
        # this heuristic will work virtually all the time.
        if (self.content_type and
                'application/x-www-form-urlencoded' in self.content_type):

            # NOTE(kgriffs): This assumes self.stream has been patched
            # above in the case of wsgiref, so that self.content_length
            # is not needed. Normally we just avoid accessing
            # self.content_length, because it is a little expensive
            # to call. We could cache self.content_length, but the
            # overhead to do that won't usually be helpful, since
            # content length will only ever be read once per
            # request in most cases.
            body = self.stream.read()

            # NOTE(kgriffs): According to http://goo.gl/6rlcux the
            # body should be US-ASCII. Enforcing this also helps
            # catch malicious input.
            try:
                body = body.decode('ascii')
            except UnicodeDecodeError:
                body = None
                self.log_error('Non-ASCII characters found in form body '
                               'with Content-Type of '
                               'application/x-www-form-urlencoded. Body '
                               'will be ignored.')

            if body:
                extra_params = uri.parse_query_string(uri.decode(body))
                self._params.update(extra_params)
Esempio n. 19
0
    def on_post(self, req, resp):
        form_body = uri.parse_query_string(req.context['body'])

        try:
            template_subject = form_body['templateSubject']
            template_body = form_body['templateBody']
            application = form_body['application']
        except KeyError:
            raise HTTPBadRequest('Missing keys from post body', '')

        if not application:
            resp.body = ujson.dumps({'error': 'No application found'})
            resp.status = falcon.HTTP_400
            return

        app_json = get_local(req, 'applications/%s' % application)
        sample_context_str = app_json.get('sample_context')
        if not sample_context_str:
            resp.body = ujson.dumps({'error': 'Missing sample_context from application config'})
            resp.status = falcon.HTTP_400
            logger.error('Missing sample context for app %s', application)
            return

        try:
            sample_context = ujson.loads(sample_context_str)
        except Exception:
            resp.body = ujson.dumps({'error': 'Invalid application sample_context'})
            resp.status = falcon.HTTP_400
            logger.exception('Bad sample context for app %s', application)
            return

        # TODO: also move iris meta var to api
        iris_sample_context = {
            "message_id": 5456900,
            "target": "user",
            "priority": "Urgent",
            "application": "Autoalerts",
            "plan": "default plan",
            "plan_id": 1843,
            "incident_id": 178293332,
            "template": "default template"
        }
        sample_context['iris'] = iris_sample_context

        environment = SandboxedEnvironment()

        try:
            subject_template = environment.from_string(template_subject)
            body_template = environment.from_string(template_body)
        except Exception as e:
            resp.body = ujson.dumps({'error': str(e), 'lineno': e.lineno})
            resp.status = falcon.HTTP_400
        else:
            resp.body = ujson.dumps({
                'template_subject': subject_template.render(sample_context),
                'template_body': body_template.render(sample_context)
            })
Esempio n. 20
0
def get_query_endtime_timestamp(req):
    try:
        params = parse_query_string(req.query_string)
        if 'end_time' in params:
            return _convert_time_string(params['end_time'])
        else:
            return None
    except Exception as ex:
        LOG.debug(ex)
        raise falcon.HTTPBadRequest('Bad request', ex.message)
Esempio n. 21
0
def get_query_period(req):
    try:
        params = parse_query_string(req.query_string)
        if 'period' in params:
            return params['period']
        else:
            return None
    except Exception as ex:
        LOG.debug(ex)
        raise falcon.HTTPBadRequest('Bad request', ex.message)
Esempio n. 22
0
    def deserialize(self, stream, content_type, content_length):
        body = stream.read()

        # NOTE(kgriffs): According to http://goo.gl/6rlcux the
        # body should be US-ASCII. Enforcing this also helps
        # catch malicious input.
        body = body.decode('ascii')

        return parse_query_string(body,
                                  keep_blank=self.keep_blank,
                                  csv=self.csv)
Esempio n. 23
0
 def _deserialize(self, body):
     try:
         # NOTE(kgriffs): According to http://goo.gl/6rlcux the
         # body should be US-ASCII. Enforcing this also helps
         # catch malicious input.
         body = body.decode('ascii')
         return parse_query_string(body,
                                   keep_blank=self._keep_blank,
                                   csv=self._csv)
     except Exception as err:
         raise errors.MediaMalformedError('URL-encoded') from err
Esempio n. 24
0
def generate_formdata(req, resp, params):
    """sets prarams['form'] to pass to every endpoint.
    """
    #print "here"
    form = dict()
    files = dict()
    if req.method == 'GET':
        di = parse_query_string(req.query_string)
        form = dict(di)
        params['form'], params['files'] = dict(form), dict(files)
    return True
Esempio n. 25
0
def generate_formdata(req, resp, params):
    """sets prarams['form'] to pass to every endpoint.
    """
    print "here"
    form = dict()
    files = dict()
    if req.method == 'GET':
        di = parse_query_string(req.query_string)
        form = dict(di)
        params['form'], params['files'] = dict(form), dict(files)
    else:
        if 'json' in req.get_header('content-type', None):
            form = json.load(req.stream)
            params['form'], params['files'] = dict(form), dict(files)
        else:
            mimetype, options = parse_options_header(
                req.get_header('content-type'))
            print mimetype
            data = req.stream.read()
            #print data
            environ = {
                'wsgi.input': StringIO(data),
                'CONTENT_LENGTH': str(len(data)),
                'CONTENT_TYPE': req.get_header('content-type'),
                'REQUEST_METHOD': 'POST'
            }
            stream, tempform, tempfiles = parse_form_data(environ)
            print "tempform", tempform
            print "stream", stream
            print "tempfiles", tempfiles
            for item in tempform:
                form[item] = tempform[item]
            di = parse_query_string(req.query_string)
            for item in di:
                form[item] = di[item]
            for item in tempfiles:
                files[item] = tempfiles[item]
            params['form'], params['files'] = dict(form), dict(files)
            print "test"
    return True
Esempio n. 26
0
    def on_get(self, req, resp):
        """
        GET handler of match service

        :param req:
            Get string like ?first_id=X&second_id=Y
            where first_id and second_id are vars filled with id-s to be checked. X and Y in this case are ints!
        :param resp:
            JSON + HTTP/resp code depends of algorithm branch, see the code
        :return:
        """
        query = uri.parse_query_string(req.query_string)
        # if [x for x in query if x not in ['first_id', 'second_id']]:
        #     raise
        try:
            query['first_id'] = int(query['first_id'])
            query['second_id'] = int(query['second_id'])
        except(KeyError, TypeError):
            logger.warn("'runtime:endpoint.ServiceEndpoint.on_get' parsing query parameters error")
            resp.status = falcon.HTTP_500
            resp.body = ujson.dumps({
                'status': 'error',
                'note': 'query error'
            })
            return

        sets_dict = {x: set(redis_client.smembers(query[x])) for x in ['first_id', 'second_id']}

        empty_ids = [x[0] for x in sets_dict.items() if x[1] == set([])]
        if len(empty_ids) > 0:
            resp.status = falcon.HTTP_404
            resp.body = ujson.dumps({
                'status': 'not_found',
                'ids': empty_ids,
                'note': "some id's are not found in db"
            })
        else:
            intersect_set = reduce(lambda l, k: l & k, sets_dict.values())
            if len(intersect_set) > 0:
                resp.status = falcon.HTTP_200
                resp.body = ujson.dumps({
                    'status': 'not_connected',
                    'id': [query['first_id'], query['second_id']]
                })
            else:
                resp.status = falcon.HTTP_200
                resp.body = ujson.dumps({
                    'status': 'connected',
                    'id': [query['first_id'], query['second_id']]
                })
Esempio n. 27
0
def get_x_tenant_or_tenant_id(req, delegate_authorized_roles):
    """Evaluates whether the tenant ID or cross tenant ID should be returned.
    
    :param req: HTTP request object.
    :param delegate_authorized_roles: List of authorized roles that have
    delegate privileges.
    :returns: Returns the cross tenant or tenant ID.
    """
    if is_in_role(req, delegate_authorized_roles):
        params = parse_query_string(req.query_string)
        if 'tenant_id' in params:
            tenant_id = params['tenant_id']
            return tenant_id
    return get_tenant_id(req)
Esempio n. 28
0
def generate_formdata(req, resp, params):
    form = dict()
    files = dict()
    if req.method == 'GET':
        di = parse_query_string(req.query_string)
        form = dict(di)
        params['form'], params['files'] = dict(form), dict(files)
    else:
        if 'json' in req.get_header('content-type', None):
            #if the method type is post "form" variable below can contain
            #only either the post body or the quer parameter at once, modify
            #umcomment the below commented line to store query parameters in "form"
            form = json.load(req.stream)
            #form = dict(parse_query_string(req.query_string))
            params['form'], params['files'] = dict(form), dict(files)
        else:
            mimetype, options = parse_options_header(
                req.get_header('content-type'))
            data = req.stream.read()
            environ = {
                'wsgi.input': StringIO(data),
                'CONTENT_LENGTH': str(len(data)),
                'CONTENT_TYPE': req.get_header('content-type'),
                'REQUEST_METHOD': 'POST'
            }
            stream, tempform, tempfiles = parse_form_data(environ)
            for item in tempform:
                form[item] = tempform[item]
            di = parse_query_string(req.query_string)
            for item in di:
                form[item] = di[item]
            for item in tempfiles:
                files[item] = tempfiles[item]
            params['form'], params['files'] = dict(form), dict(files)
    #print form
    #print params
    return True
Esempio n. 29
0
def get_query_statistics(req):
    try:
        params = parse_query_string(req.query_string)
        if 'statistics' in params:
            statistics = params['statistics'].split(',')
            statistics = [statistic.lower() for statistic in statistics]
            if not all(statistic in ['avg', 'min', 'max', 'count', 'sum'] for
                       statistic in statistics):
                raise Exception("Invalid statistic")
            return statistics
        else:
            raise Exception("Missing statistics")
    except Exception as ex:
        LOG.debug(ex)
        raise falcon.HTTPBadRequest('Bad request', ex.message)
Esempio n. 30
0
    def deserialize(self, stream, content_type, content_length):
        body = stream.read()

        # NOTE(kgriffs): According to http://goo.gl/6rlcux the
        # body should be US-ASCII. Enforcing this also helps
        # catch malicious input.
        body = body.decode('ascii')

        # TODO(vytas): We are not short-circuiting here for performance (as
        #   empty URL-encoded payload should not be a common case), but to work
        #   around #1600
        if not body:
            return {}

        return parse_query_string(body,
                                  keep_blank=self.keep_blank,
                                  csv=self.csv)
Esempio n. 31
0
def parse_form_body(req):
    if (req.content_type is not None
            and "application/x-www-form-urlencoded" in req.content_type):
        body = req.stream.read()
        try:
            body = body.decode("ascii")
        except UnicodeDecodeError:
            body = None
            req.log_error("Non-ASCII characters found in form body "
                          "with Content-Type of "
                          "application/x-www-form-urlencoded. Body "
                          "will be ignored.")

        if body:
            return parse_query_string(
                body, keep_blank_qs_values=req.options.keep_blank_qs_values)
    return {}
Esempio n. 32
0
def get_query_name(req, name_required=False):
    """
    Returns the query param "name" if supplied.
    :param req: HTTP request object.
    """
    try:
        params = parse_query_string(req.query_string)
        if 'name' in params:
            name = params['name']
            return name
        else:
            if name_required:
                raise Exception("Missing name")
            else:
                return ''
    except Exception as ex:
        LOG.debug(ex)
        raise falcon.HTTPBadRequest('Bad request', ex.message)
Esempio n. 33
0
    def on_post(self, req, resp):
        form_body = uri.parse_query_string(req.context['body'])

        try:
            username = form_body['username']
            password = form_body['password']
        except KeyError:
            raise HTTPFound('/login')

        if self.auth_manager.authenticate(username, password):
            logger.info('Successful login for %s', username)
            auth.login_user(req, username)
        else:
            logger.warn('Failed login for %s', username)
            raise HTTPFound('/login')

        url = req.get_param('next')

        if not url or url.startswith('/'):
            raise HTTPFound(url or default_route)
        else:
            raise HTTPBadRequest('Invalid next parameter', '')
Esempio n. 34
0
def get_query_dimensions(req):
    """Gets and parses the query param dimensions.
    
    :param req: HTTP request object.
    :return: Returns the dimensions as a JSON object
    :raises falcon.HTTPBadRequest: If dimensions are malformed.
    """
    try:
        params = parse_query_string(req.query_string)
        dimensions = {}
        if 'dimensions' in params:
            dimensions_str = params['dimensions']
            dimensions_str_array = dimensions_str.split(',')
            for dimension in dimensions_str_array:
                dimension_name_value = dimension.split(':')
                if len(dimension_name_value) == 2:
                    dimensions[dimension_name_value[0]] = dimension_name_value[
                        1]
                else:
                    raise Exception('Dimensions are malformed')
        return dimensions
    except Exception as ex:
        LOG.debug(ex)
        raise falcon.HTTPBadRequest('Bad request', ex.message)
Esempio n. 35
0
    def test_to_query_str_encoding(self, params, csv):
        query_str = falcon.to_query_str(params,
                                        comma_delimited_lists=csv,
                                        prefix=False)

        assert uri.parse_query_string(query_str, csv=csv) == params
Esempio n. 36
0
    def __init__(self, env):
        """Initialize attributes based on a WSGI environment dict

        Note: Request is not meant to be instantiated directory by responders.

        Args:
            env: A WSGI environment dict passed in from the server. See also
                the PEP-3333 spec.

        """
        self.env = env

        self._wsgierrors = env['wsgi.errors']
        self.stream = env['wsgi.input']
        self.method = env['REQUEST_METHOD']

        # Normalize path
        path = env['PATH_INFO']
        if path:
            if len(path) != 1 and path.endswith('/'):
                self.path = path[:-1]
            else:
                self.path = path
        else:
            self.path = '/'

        # QUERY_STRING isn't required to be in env, so let's check
        # PERF: if...in is faster than using env.get(...)
        if 'QUERY_STRING' in env and env['QUERY_STRING']:

            # TODO(kgriffs): Should this escape individual values instead
            # of the entire string? The way it is now, this:
            #
            #   x=ab%2Bcd%3D42%2C9
            #
            # becomes this:
            #
            #   x=ab+cd=42,9
            #
            self.query_string = uri.decode(env['QUERY_STRING'])

        else:
            self.query_string = six.text_type()

        # PERF: Don't parse it if we don't have to!
        if self.query_string:
            self._params = uri.parse_query_string(self.query_string)
        else:
            self._params = {}

        helpers.normalize_headers(env)
        self._cached_headers = {}

        self._cached_uri = None
        self._cached_relative_uri = None

        # NOTE(kgriffs): Wrap wsgi.input if needed to make read() more robust,
        # normalizing semantics between, e.g., gunicorn and wsgiref.
        if isinstance(self.stream, NativeStream):  # pragma: nocover
            # NOTE(kgriffs): coverage can't detect that this *is* actually
            # covered since the test that does so uses multiprocessing.
            self.stream = helpers.Body(self.stream, self.content_length)
Esempio n. 37
0
    def __init__(self, env, options=None):
        global _maybe_wrap_wsgi_stream

        self.env = env
        self.options = options if options else RequestOptions()

        self._wsgierrors = env["wsgi.errors"]
        self.stream = env["wsgi.input"]
        self.method = env["REQUEST_METHOD"]

        # Normalize path
        path = env["PATH_INFO"]
        if path:
            if six.PY3:
                # PEP 3333 specifies that PATH_INFO variable are always
                # "bytes tunneled as latin-1" and must be encoded back
                path = path.encode("latin1").decode("utf-8", "replace")

            if len(path) != 1 and path.endswith("/"):
                self.path = path[:-1]
            else:
                self.path = path
        else:
            self.path = "/"

        # PERF(ueg1990): try/catch cheaper and faster (and more Pythonic)
        try:
            self.query_string = env["QUERY_STRING"]
        except KeyError:
            self.query_string = ""
            self._params = {}
        else:
            if self.query_string:
                self._params = parse_query_string(
                    self.query_string, keep_blank_qs_values=self.options.keep_blank_qs_values
                )

            else:
                self._params = {}

        self._cookies = None

        self._cached_headers = None
        self._cached_uri = None
        self._cached_relative_uri = None
        self._cached_access_route = None

        try:
            self.content_type = self.env["CONTENT_TYPE"]
        except KeyError:
            self.content_type = None

        # NOTE(kgriffs): Wrap wsgi.input if needed to make read() more robust,
        # normalizing semantics between, e.g., gunicorn and wsgiref.
        if _maybe_wrap_wsgi_stream:
            if isinstance(self.stream, (NativeStream, InputWrapper)):
                self._wrap_stream()
            else:
                # PERF(kgriffs): If self.stream does not need to be wrapped
                # this time, it never needs to be wrapped since the server
                # will continue using the same type for wsgi.input.
                _maybe_wrap_wsgi_stream = False

        # PERF(kgriffs): Technically, we should spend a few more
        # cycles and parse the content type for real, but
        # this heuristic will work virtually all the time.
        if (
            self.options.auto_parse_form_urlencoded
            and self.content_type is not None
            and "application/x-www-form-urlencoded" in self.content_type
        ):
            self._parse_form_urlencoded()

        if self.context_type is None:
            # Literal syntax is more efficient than using dict()
            self.context = {}
        else:
            self.context = self.context_type()
Esempio n. 38
0
    def __init__(self, scope, receive, first_event=None, options=None):

        # =====================================================================
        # Prepare headers
        # =====================================================================

        req_headers = {}
        for header_name, header_value in scope['headers']:
            # NOTE(kgriffs): According to ASGI 3.0, header names are always
            #   lowercased, and both name and value are byte strings. Although
            #   technically header names and values are restricted to US-ASCII
            #   we decode later (just-in-time) using the default 'utf-8' because
            #   it is a little faster than passing an encoding option (except
            #   under Cython).
            #
            #   The reason we wait to decode is that the typical app will not
            #   need to decode all request headers, and we usually can just
            #   leave the header name as a byte string and look it up that way.
            #

            # NOTE(kgriffs): There are no standard request headers that
            #   allow multiple instances to appear in the request while also
            #   disallowing list syntax.
            if (header_name not in req_headers
                    or header_name in _SINGLETON_HEADERS_BYTESTR):
                req_headers[header_name] = header_value
            else:
                req_headers[header_name] += b',' + header_value

        self._asgi_headers = req_headers
        # PERF(vytas): Fall back to class variable(s) when unset.
        # self._cached_headers = None

        # =====================================================================
        #  Misc.
        # =====================================================================

        # PERF(vytas): Fall back to class variable(s) when unset.
        # self._asgi_server_cached = None  # Lazy
        self.scope = scope
        self.is_websocket = scope['type'] == 'websocket'

        self.options = options if options else request.RequestOptions()

        # PERF(vytas): Fall back to class variable(s) when unset.
        # self._wsgierrors = None
        self.method = 'GET' if self.is_websocket else scope['method']

        self.uri_template = None
        # PERF(vytas): Fall back to class variable(s) when unset.
        # self._media = _UNSET
        # self._media_error = None

        # TODO(kgriffs): ASGI does not specify whether 'path' may be empty,
        #   as was allowed for WSGI.
        path = scope['path'] or '/'

        if (self.options.strip_url_path_trailing_slash and len(path) != 1
                and path.endswith('/')):
            self.path = path[:-1]
        else:
            self.path = path

        query_string = scope['query_string'].decode()
        self.query_string = query_string
        if query_string:
            self._params = parse_query_string(
                query_string,
                keep_blank=self.options.keep_blank_qs_values,
                csv=self.options.auto_parse_qs_csv,
            )

        else:
            self._params = {}

        # PERF(vytas): Fall back to class variable(s) when unset.
        # self._cached_access_route = None
        # self._cached_forwarded = None
        # self._cached_forwarded_prefix = None
        # self._cached_forwarded_uri = None
        # self._cached_prefix = None
        # self._cached_relative_uri = None
        # self._cached_uri = None

        if self.method == 'GET':
            # NOTE(vytas): We do not really expect the Content-Type to be
            #   non-ASCII, however we assume ISO-8859-1 here for maximum
            #   compatibility with WSGI.

            # PERF(kgriffs): Normally we expect no Content-Type header, so
            #   use this pattern which is a little bit faster than dict.get()
            if b'content-type' in req_headers:
                self.content_type = req_headers[b'content-type'].decode(
                    'latin1')
            else:
                self.content_type = None
        else:
            # PERF(kgriffs): This is the most performant pattern when we expect
            #   the key to be present most of the time.
            try:
                self.content_type = req_headers[b'content-type'].decode(
                    'latin1')
            except KeyError:
                self.content_type = None

        # =====================================================================
        # The request body stream is created lazily
        # =====================================================================

        # NOTE(kgriffs): The ASGI spec states that "you should not trigger
        #   on a connection opening alone". I take this to mean that the app
        #   should have the opportunity to respond with a 401, for example,
        #   without having to first read any of the body. This is accomplished
        #   in Falcon by only reading the first data event when the app attempts
        #   to read from req.stream for the first time, and in uvicorn
        #   (for example) by not confirming a 100 Continue request unless
        #   the app calls receive() to read the request body.

        # PERF(vytas): Fall back to class variable(s) when unset.
        # self._stream = None
        self._receive = receive
        self._first_event = first_event

        # =====================================================================
        # Create a context object
        # =====================================================================

        self.context = self.context_type()
Esempio n. 39
0
    def __init__(self, env):
        self.env = env

        if self.context_type is None:
            # Literal syntax is more efficient than using dict()
            self.context = {}
        else:
            # pylint will detect this as not-callable because it only sees the
            # declaration of None, not whatever type a subclass may have set.
            self.context = self.context_type()  # pylint: disable=not-callable

        self._wsgierrors = env['wsgi.errors']
        self.stream = env['wsgi.input']
        self.method = env['REQUEST_METHOD']

        # Normalize path
        path = env['PATH_INFO']
        if path:
            if len(path) != 1 and path.endswith('/'):
                self.path = path[:-1]
            else:
                self.path = path
        else:
            self.path = '/'

        # QUERY_STRING isn't required to be in env, so let's check
        # PERF: if...in is faster than using env.get(...)
        if 'QUERY_STRING' in env and env['QUERY_STRING']:

            # TODO(kgriffs): Should this escape individual values instead
            # of the entire string? The way it is now, this:
            #
            #   x=ab%2Bcd%3D42%2C9
            #
            # becomes this:
            #
            #   x=ab+cd=42,9
            #
            self.query_string = uri.decode(env['QUERY_STRING'])

        else:
            self.query_string = six.text_type()

        # PERF: Don't parse it if we don't have to!
        if self.query_string:
            self._params = uri.parse_query_string(self.query_string)
        else:
            self._params = {}

        helpers.normalize_headers(env)
        self._cached_headers = {}

        self._cached_uri = None
        self._cached_relative_uri = None

        self.content_type = self._get_header_by_wsgi_name('HTTP_CONTENT_TYPE')

        # NOTE(kgriffs): Wrap wsgi.input if needed to make read() more robust,
        # normalizing semantics between, e.g., gunicorn and wsgiref.
        if isinstance(self.stream, NativeStream):  # pragma: nocover
            # NOTE(kgriffs): coverage can't detect that this *is* actually
            # covered since the test that does so uses multiprocessing.
            self.stream = helpers.Body(self.stream, self.content_length)

        self._parse_form_urlencoded()
Esempio n. 40
0
    def __init__(self, env, options=None):
        global _maybe_wrap_wsgi_stream

        self.env = env
        self.options = options if options else RequestOptions()

        self._wsgierrors = env['wsgi.errors']
        self.stream = env['wsgi.input']
        self.method = env['REQUEST_METHOD']

        # Normalize path
        path = env['PATH_INFO']
        if path:
            if six.PY3:
                # PEP 3333 specifies that PATH_INFO variable are always
                # "bytes tunneled as latin-1" and must be encoded back
                path = path.encode('latin1').decode('utf-8', 'replace')

            if len(path) != 1 and path.endswith('/'):
                self.path = path[:-1]
            else:
                self.path = path
        else:
            self.path = '/'

        # PERF(ueg1990): try/catch cheaper and faster (and more Pythonic)
        try:
            self.query_string = env['QUERY_STRING']
        except KeyError:
            self.query_string = ''
            self._params = {}
        else:
            if self.query_string:
                self._params = parse_query_string(
                    self.query_string,
                    keep_blank_qs_values=self.options.keep_blank_qs_values,
                    parse_qs_csv=self.options.auto_parse_qs_csv,
                )

            else:
                self._params = {}

        self._cookies = None

        self._cached_headers = None
        self._cached_uri = None
        self._cached_relative_uri = None
        self._cached_access_route = None

        try:
            self.content_type = self.env['CONTENT_TYPE']
        except KeyError:
            self.content_type = None

        # NOTE(kgriffs): Wrap wsgi.input if needed to make read() more robust,
        # normalizing semantics between, e.g., gunicorn and wsgiref.
        if _maybe_wrap_wsgi_stream:
            if isinstance(self.stream, (
                    NativeStream,
                    InputWrapper,
            )):
                self._wrap_stream()
            else:
                # PERF(kgriffs): If self.stream does not need to be wrapped
                # this time, it never needs to be wrapped since the server
                # will continue using the same type for wsgi.input.
                _maybe_wrap_wsgi_stream = False

        # PERF(kgriffs): Technically, we should spend a few more
        # cycles and parse the content type for real, but
        # this heuristic will work virtually all the time.
        if (self.options.auto_parse_form_urlencoded
                and self.content_type is not None
                and 'application/x-www-form-urlencoded' in self.content_type):
            self._parse_form_urlencoded()

        if self.context_type is None:
            # Literal syntax is more efficient than using dict()
            self.context = {}
        else:
            self.context = self.context_type()
Esempio n. 41
0
    def __init__(self, env):
        self.env = env

        if self.context_type is None:
            # Literal syntax is more efficient than using dict()
            self.context = {}
        else:
            # pylint will detect this as not-callable because it only sees the
            # declaration of None, not whatever type a subclass may have set.
            self.context = self.context_type()  # pylint: disable=not-callable

        self._wsgierrors = env['wsgi.errors']
        self.stream = env['wsgi.input']
        self.method = env['REQUEST_METHOD']

        # Normalize path
        path = env['PATH_INFO']
        if path:
            if len(path) != 1 and path.endswith('/'):
                self.path = path[:-1]
            else:
                self.path = path
        else:
            self.path = '/'

        # QUERY_STRING isn't required to be in env, so let's check
        # PERF: if...in is faster than using env.get(...)
        if 'QUERY_STRING' in env and env['QUERY_STRING']:

            # TODO(kgriffs): Should this escape individual values instead
            # of the entire string? The way it is now, this:
            #
            #   x=ab%2Bcd%3D42%2C9
            #
            # becomes this:
            #
            #   x=ab+cd=42,9
            #
            self.query_string = uri.decode(env['QUERY_STRING'])

        else:
            self.query_string = six.text_type()

        # PERF: Don't parse it if we don't have to!
        if self.query_string:
            self._params = uri.parse_query_string(self.query_string)
        else:
            self._params = {}

        helpers.normalize_headers(env)
        self._cached_headers = {}

        self._cached_uri = None
        self._cached_relative_uri = None

        self.content_type = self._get_header_by_wsgi_name('HTTP_CONTENT_TYPE')

        # NOTE(kgriffs): Wrap wsgi.input if needed to make read() more robust,
        # normalizing semantics between, e.g., gunicorn and wsgiref.
        if isinstance(self.stream, NativeStream):  # pragma: nocover
            # NOTE(kgriffs): coverage can't detect that this *is* actually
            # covered since the test that does so uses multiprocessing.
            self.stream = helpers.Body(self.stream, self.content_length)

        # PERF(kgriffs): Technically, we should spend a few more
        # cycles and parse the content type for real, but
        # this heuristic will work virtually all the time.
        if (self.content_type and
                'application/x-www-form-urlencoded' in self.content_type):

            # NOTE(kgriffs): This assumes self.stream has been patched
            # above in the case of wsgiref, so that self.content_length
            # is not needed. Normally we just avoid accessing
            # self.content_length, because it is a little expensive
            # to call. We could cache self.content_length, but the
            # overhead to do that won't usually be helpful, since
            # content length will only ever be read once per
            # request in most cases.
            body = self.stream.read()
            body = body.decode('ascii')

            extra_params = uri.parse_query_string(uri.decode(body))
            self._params.update(extra_params)
Esempio n. 42
0
    def __init__(self, scope, receive, options=None):

        # =====================================================================
        # Prepare headers
        # =====================================================================

        req_headers = {}
        for header_name, header_value in scope['headers']:
            # NOTE(kgriffs): According to ASGI 3.0, header names are always
            #   lowercased, and both name and value are byte strings. Although
            #   technically header names and values are restricted to US-ASCII
            #   we decode using the default 'utf-8' because it is a little
            #   faster than passing an encoding option.
            header_name = header_name.decode()
            header_value = header_value.decode()

            # NOTE(kgriffs): There are no standard request headers that
            #   allow multiple instances to appear in the request while also
            #   disallowing list syntax.
            if header_name not in req_headers or header_name in SINGLETON_HEADERS:
                req_headers[header_name] = header_value
            else:
                req_headers[header_name] += ',' + header_value

        self._asgi_headers = req_headers

        # =====================================================================
        #  Misc.
        # =====================================================================

        self._asgi_server_cached = None  # Lazy

        self.scope = scope
        self.options = options if options else falcon.request.RequestOptions()

        self._wsgierrors = None
        self.method = scope['method']

        self.uri_template = None
        self._media = None

        # TODO(kgriffs): ASGI does not specify whether 'path' may be empty,
        #   as was allowed for WSGI.
        path = scope['path'] or '/'

        if (self.options.strip_url_path_trailing_slash and len(path) != 1
                and path.endswith('/')):
            self.path = path[:-1]
        else:
            self.path = path

        query_string = scope['query_string'].decode()
        self.query_string = query_string
        if query_string:
            self._params = parse_query_string(
                query_string,
                keep_blank=self.options.keep_blank_qs_values,
                csv=self.options.auto_parse_qs_csv,
            )

        else:
            self._params = {}

        self._cached_access_route = None
        self._cached_forwarded = None
        self._cached_forwarded_prefix = None
        self._cached_forwarded_uri = None
        self._cached_headers = req_headers
        self._cached_prefix = None
        self._cached_relative_uri = None
        self._cached_uri = None

        if self.method == 'GET':
            # PERF(kgriffs): Normally we expect no Content-Type header, so
            #   use this pattern which is a little bit faster than dict.get()
            if 'content-type' in req_headers:
                self.content_type = req_headers['content-type']
            else:
                self.content_type = None
        else:
            # PERF(kgriffs): This is the most performant pattern when we expect
            #   the key to be present most of the time.
            try:
                self.content_type = req_headers['content-type']
            except KeyError:
                self.content_type = None

        # =====================================================================
        # The request body stream is created lazily
        # =====================================================================

        # NOTE(kgriffs): The ASGI spec states that "you should not trigger
        #   on a connection opening alone". I take this to mean that the app
        #   should have the opportunity to respond with a 401, for example,
        #   without having to first read any of the body. This is accomplished
        #   in Falcon by only reading the first data event when the app attempts
        #   to read from req.stream for the first time, and in uvicorn
        #   (for example) by not confirming a 100 Continue request unless
        #   the app calls receive() to read the request body.

        self._stream = None
        self._receive = receive

        # =====================================================================
        # Create a context object
        # =====================================================================

        self.context = self.context_type()
Esempio n. 43
0
    def __init__(self, env, options=None):
        global _maybe_wrap_wsgi_stream

        self.env = env
        self.options = options if options else RequestOptions()

        if self.context_type is None:
            # Literal syntax is more efficient than using dict()
            self.context = {}
        else:
            # pylint will detect this as not-callable because it only sees the
            # declaration of None, not whatever type a subclass may have set.
            self.context = self.context_type()  # pylint: disable=not-callable

        self._wsgierrors = env['wsgi.errors']
        self.stream = env['wsgi.input']
        self.method = env['REQUEST_METHOD']

        # Normalize path
        path = env['PATH_INFO']
        if path:
            if len(path) != 1 and path.endswith('/'):
                self.path = path[:-1]
            else:
                self.path = path
        else:
            self.path = '/'

        # PERF(kgriffs): if...in is faster than using env.get(...)
        if 'QUERY_STRING' in env:
            self.query_string = env['QUERY_STRING']

            if self.query_string:
                self._params = parse_query_string(
                    self.query_string,
                    keep_blank_qs_values=self.options.keep_blank_qs_values,
                )

            else:
                self._params = {}

        else:
            self.query_string = ''
            self._params = {}

        self._cookies = None

        self._cached_headers = None
        self._cached_uri = None
        self._cached_relative_uri = None

        try:
            self.content_type = self.env['CONTENT_TYPE']
        except KeyError:
            self.content_type = None

        # NOTE(kgriffs): Wrap wsgi.input if needed to make read() more robust,
        # normalizing semantics between, e.g., gunicorn and wsgiref.
        if _maybe_wrap_wsgi_stream:
            if isinstance(self.stream, NativeStream):
                # NOTE(kgriffs): This is covered by tests, it's just that
                # coverage can't figure this out for some reason (TBD).
                self._wrap_stream()  # pragma nocover
            else:
                # PERF(kgriffs): If self.stream does not need to be wrapped
                # this time, it never needs to be wrapped since the server
                # will continue using the same type for wsgi.input.
                _maybe_wrap_wsgi_stream = False

        # PERF(kgriffs): Technically, we should spend a few more
        # cycles and parse the content type for real, but
        # this heuristic will work virtually all the time.
        if (self.content_type is not None
                and 'application/x-www-form-urlencoded' in self.content_type):
            self._parse_form_urlencoded()
Esempio n. 44
0
def urlencoded(body, charset='ascii', **kwargs):
    """Converts query strings into native Python objects"""
    return parse_query_string(text(body, charset=charset), False)
Esempio n. 45
0
 def test_parse_query_string_edge_cases(self, query_string, keep_blank,
                                        expected):
     assert uri.parse_query_string(query_string,
                                   keep_blank=keep_blank) == (expected)
Esempio n. 46
0
    def __init__(self, env):
        """Initialize attributes based on a WSGI environment dict

        Note: Request is not meant to be instantiated directory by responders.

        Args:
            env: A WSGI environment dict passed in from the server. See also
                the PEP-3333 spec.

        """
        self.env = env

        self._wsgierrors = env['wsgi.errors']
        self.stream = env['wsgi.input']
        self.method = env['REQUEST_METHOD']

        # Normalize path
        path = env['PATH_INFO']
        if path:
            if len(path) != 1 and path.endswith('/'):
                self.path = path[:-1]
            else:
                self.path = path
        else:
            self.path = '/'

        # QUERY_STRING isn't required to be in env, so let's check
        # PERF: if...in is faster than using env.get(...)
        if 'QUERY_STRING' in env and env['QUERY_STRING']:

            # TODO(kgriffs): Should this escape individual values instead
            # of the entire string? The way it is now, this:
            #
            #   x=ab%2Bcd%3D42%2C9
            #
            # becomes this:
            #
            #   x=ab+cd=42,9
            #
            self.query_string = uri.decode(env['QUERY_STRING'])

        else:
            self.query_string = six.text_type()

        # PERF: Don't parse it if we don't have to!
        if self.query_string:
            self._params = uri.parse_query_string(self.query_string)
        else:
            self._params = {}

        helpers.normalize_headers(env)
        self._cached_headers = {}

        self._cached_uri = None
        self._cached_relative_uri = None

        # NOTE(kgriffs): Wrap wsgi.input if needed to make read() more robust,
        # normalizing semantics between, e.g., gunicorn and wsgiref.
        if isinstance(self.stream, NativeStream):  # pragma: nocover
            # NOTE(kgriffs): coverage can't detect that this *is* actually
            # covered since the test that does so uses multiprocessing.
            self.stream = helpers.Body(self.stream, self.content_length)
Esempio n. 47
0
    def __init__(self, env, options=None):
        self.env = env
        self.options = options if options else RequestOptions()

        self._wsgierrors = env['wsgi.errors']
        self.method = env['REQUEST_METHOD']

        self.uri_template = None

        # Normalize path
        path = env['PATH_INFO']
        if path:
            if six.PY3:
                # PEP 3333 specifies that PATH_INFO variable are always
                # "bytes tunneled as latin-1" and must be encoded back
                path = path.encode('latin1').decode('utf-8', 'replace')

            if len(path) != 1 and path.endswith('/'):
                self.path = path[:-1]
            else:
                self.path = path
        else:
            self.path = '/'

        # PERF(ueg1990): try/catch cheaper and faster (and more Pythonic)
        try:
            self.query_string = env['QUERY_STRING']
        except KeyError:
            self.query_string = ''
            self._params = {}
        else:
            if self.query_string:
                self._params = parse_query_string(
                    self.query_string,
                    keep_blank_qs_values=self.options.keep_blank_qs_values,
                    parse_qs_csv=self.options.auto_parse_qs_csv,
                )

            else:
                self._params = {}

        self._cookies = None

        self._cached_headers = None
        self._cached_uri = None
        self._cached_relative_uri = None
        self._cached_access_route = None

        try:
            self.content_type = self.env['CONTENT_TYPE']
        except KeyError:
            self.content_type = None

        # NOTE(kgriffs): Wrap wsgi.input if needed to make read() more robust,
        # normalizing semantics between, e.g., gunicorn and wsgiref.
        if not Request._wsgi_input_type_known:
            Request._always_wrap_wsgi_input = isinstance(
                env['wsgi.input'],
                (NativeStream, InputWrapper)
            )

            Request._wsgi_input_type_known = True

        if Request._always_wrap_wsgi_input:
            # TODO(kgriffs): In Falcon 2.0, stop wrapping stream since it is
            # less useful now that we have bounded_stream.
            self.stream = self._get_wrapped_wsgi_input()
            self._bounded_stream = self.stream
        else:
            self.stream = env['wsgi.input']
            self._bounded_stream = None  # Lazy wrapping

        # PERF(kgriffs): Technically, we should spend a few more
        # cycles and parse the content type for real, but
        # this heuristic will work virtually all the time.
        if (
            self.options.auto_parse_form_urlencoded and
            self.content_type is not None and
            'application/x-www-form-urlencoded' in self.content_type and

            # NOTE(kgriffs): Within HTTP, a payload for a GET or HEAD
            # request has no defined semantics, so we don't expect a
            # body in those cases. We would normally not expect a body
            # for OPTIONS either, but RFC 7231 does allow for it.
            self.method not in ('GET', 'HEAD')
        ):
            self._parse_form_urlencoded()

        if self.context_type is None:
            # Literal syntax is more efficient than using dict()
            self.context = {}
        else:
            self.context = self.context_type()
Esempio n. 48
0
    def __init__(self, env, options=None):
        global _maybe_wrap_wsgi_stream

        self.env = env
        self.options = options if options else RequestOptions()

        self._wsgierrors = env['wsgi.errors']
        self.stream = env['wsgi.input']
        self.method = env['REQUEST_METHOD']

        # Normalize path
        path = env['PATH_INFO']
        if path:
            if six.PY3:  # pragma: no cover
                # PEP 3333 specifies that PATH_INFO variable are always
                # "bytes tunneled as latin-1" and must be encoded back
                path = path.encode('latin1').decode('utf-8', 'replace')

            if len(path) != 1 and path.endswith('/'):
                self.path = path[:-1]
            else:
                self.path = path
        else:
            self.path = '/'

        # PERF(kgriffs): if...in is faster than using env.get(...)
        if 'QUERY_STRING' in env:
            self.query_string = env['QUERY_STRING']

            if self.query_string:
                self._params = parse_query_string(
                    self.query_string,
                    keep_blank_qs_values=self.options.keep_blank_qs_values,
                )

            else:
                self._params = {}

        else:
            self.query_string = ''
            self._params = {}

        self._cookies = None

        self._cached_headers = None
        self._cached_uri = None
        self._cached_relative_uri = None
        self._cached_access_route = None

        try:
            self.content_type = self.env['CONTENT_TYPE']
        except KeyError:
            self.content_type = None

        # NOTE(kgriffs): Wrap wsgi.input if needed to make read() more robust,
        # normalizing semantics between, e.g., gunicorn and wsgiref.
        if _maybe_wrap_wsgi_stream:
            if isinstance(self.stream, NativeStream):
                # NOTE(kgriffs): This is covered by tests, it's just that
                # coverage can't figure this out for some reason (TBD).
                self._wrap_stream()  # pragma nocover
            else:
                # PERF(kgriffs): If self.stream does not need to be wrapped
                # this time, it never needs to be wrapped since the server
                # will continue using the same type for wsgi.input.
                _maybe_wrap_wsgi_stream = False

        # PERF(kgriffs): Technically, we should spend a few more
        # cycles and parse the content type for real, but
        # this heuristic will work virtually all the time.
        if (self.content_type is not None and
                'application/x-www-form-urlencoded' in self.content_type):
            self._parse_form_urlencoded()

        if self.context_type is None:
            # Literal syntax is more efficient than using dict()
            self.context = {}
        else:
            # pylint will detect this as not-callable because it only sees the
            # declaration of None, not whatever type a subclass may have set.
            self.context = self.context_type()  # pylint: disable=not-callable
Esempio n. 49
0
    def __init__(self, env, options=None):
        self.env = env
        self.options = options if options else RequestOptions()

        self._wsgierrors = env['wsgi.errors']
        self.method = env['REQUEST_METHOD']

        self.uri_template = None

        # Normalize path
        path = env['PATH_INFO']
        if path:
            if six.PY3:
                # PEP 3333 specifies that PATH_INFO variable are always
                # "bytes tunneled as latin-1" and must be encoded back
                path = path.encode('latin1').decode('utf-8', 'replace')

            if len(path) != 1 and path.endswith('/'):
                self.path = path[:-1]
            else:
                self.path = path
        else:
            self.path = '/'

        # PERF(ueg1990): try/catch cheaper and faster (and more Pythonic)
        try:
            self.query_string = env['QUERY_STRING']
        except KeyError:
            self.query_string = ''
            self._params = {}
        else:
            if self.query_string:
                self._params = parse_query_string(
                    self.query_string,
                    keep_blank_qs_values=self.options.keep_blank_qs_values,
                    parse_qs_csv=self.options.auto_parse_qs_csv,
                )

            else:
                self._params = {}

        self._cookies = None

        self._cached_headers = None
        self._cached_uri = None
        self._cached_relative_uri = None
        self._cached_access_route = None

        try:
            self.content_type = self.env['CONTENT_TYPE']
        except KeyError:
            self.content_type = None

        # NOTE(kgriffs): Wrap wsgi.input if needed to make read() more robust,
        # normalizing semantics between, e.g., gunicorn and wsgiref.
        if not Request._wsgi_input_type_known:
            Request._always_wrap_wsgi_input = isinstance(
                env['wsgi.input'],
                (NativeStream, InputWrapper)
            )

            Request._wsgi_input_type_known = True

        if Request._always_wrap_wsgi_input:
            # TODO(kgriffs): In Falcon 2.0, stop wrapping stream since it is
            # less useful now that we have bounded_stream.
            self.stream = self._get_wrapped_wsgi_input()
            self._bounded_stream = self.stream
        else:
            self.stream = env['wsgi.input']
            self._bounded_stream = None  # Lazy wrapping

        # PERF(kgriffs): Technically, we should spend a few more
        # cycles and parse the content type for real, but
        # this heuristic will work virtually all the time.
        if (self.options.auto_parse_form_urlencoded and
                self.content_type is not None and
                'application/x-www-form-urlencoded' in self.content_type and
                self.method == 'POST'):
            self._parse_form_urlencoded()

        if self.context_type is None:
            # Literal syntax is more efficient than using dict()
            self.context = {}
        else:
            self.context = self.context_type()
Esempio n. 50
0
    def __init__(self, env):
        self.env = env

        if self.context_type is None:
            # Literal syntax is more efficient than using dict()
            self.context = {}
        else:
            # pylint will detect this as not-callable because it only sees the
            # declaration of None, not whatever type a subclass may have set.
            self.context = self.context_type()  # pylint: disable=not-callable

        self._wsgierrors = env['wsgi.errors']
        self.stream = env['wsgi.input']
        self.method = env['REQUEST_METHOD']

        # Normalize path
        path = env['PATH_INFO']
        if path:
            if len(path) != 1 and path.endswith('/'):
                self.path = path[:-1]
            else:
                self.path = path
        else:
            self.path = '/'

        # QUERY_STRING isn't required to be in env, so let's check
        # PERF: if...in is faster than using env.get(...)
        if 'QUERY_STRING' in env and env['QUERY_STRING']:

            # TODO(kgriffs): Should this escape individual values instead
            # of the entire string? The way it is now, this:
            #
            #   x=ab%2Bcd%3D42%2C9
            #
            # becomes this:
            #
            #   x=ab+cd=42,9
            #
            self.query_string = uri.decode(env['QUERY_STRING'])

        else:
            self.query_string = six.text_type()

        # PERF: Don't parse it if we don't have to!
        if self.query_string:
            self._params = uri.parse_query_string(self.query_string)
        else:
            self._params = {}

        helpers.normalize_headers(env)
        self._cached_headers = {}

        self._cached_uri = None
        self._cached_relative_uri = None

        self.content_type = self._get_header_by_wsgi_name('HTTP_CONTENT_TYPE')

        # NOTE(kgriffs): Wrap wsgi.input if needed to make read() more robust,
        # normalizing semantics between, e.g., gunicorn and wsgiref.
        if isinstance(self.stream, NativeStream):  # pragma: nocover
            # NOTE(kgriffs): coverage can't detect that this *is* actually
            # covered since the test that does so uses multiprocessing.
            self.stream = helpers.Body(self.stream, self.content_length)

        # PERF(kgriffs): Technically, we should spend a few more
        # cycles and parse the content type for real, but
        # this heuristic will work virtually all the time.
        if (self.content_type
                and 'application/x-www-form-urlencoded' in self.content_type):

            # NOTE(kgriffs): This assumes self.stream has been patched
            # above in the case of wsgiref, so that self.content_length
            # is not needed. Normally we just avoid accessing
            # self.content_length, because it is a little expensive
            # to call. We could cache self.content_length, but the
            # overhead to do that won't usually be helpful, since
            # content length will only ever be read once per
            # request in most cases.
            body = self.stream.read()
            body = body.decode('ascii')

            extra_params = uri.parse_query_string(uri.decode(body))
            self._params.update(extra_params)