Exemplo n.º 1
0
 def check_response(self,
                    data_queues,
                    response,
                    status,
                    fallback=None,
                    details=None):
     assert response.content_type == "application/json"
     assert response.headers["Access-Control-Allow-Origin"] == "*"
     assert response.headers["Access-Control-Max-Age"] == "2592000"
     if status == "ok":
         body = dict(response.json)
         if fallback:
             assert body["fallback"] == fallback
             del body["fallback"]
         assert body == self.ip_response
     elif status == "invalid_key":
         assert response.json == InvalidAPIKey().json_body()
     elif status == "not_found":
         assert response.json == LocationNotFound().json_body()
     elif status == "parse_error":
         assert response.json == ParseError(details).json_body()
     elif status == "limit_exceeded":
         assert response.json == DailyLimitExceeded().json_body()
     if status != "ok":
         self.check_queue(data_queues, 0)
Exemplo n.º 2
0
    def __call__(self):
        """Execute the view and return a response."""
        api_key = None
        api_key_text = self.parse_apikey()
        skip_check = False

        if api_key_text is None:
            self.log_count("none")
            if self.error_on_invalidkey:
                raise self.prepare_exception(InvalidAPIKey())

        if api_key_text is not None:
            try:
                api_key = get_key(self.request.db_session, api_key_text)
            except (DatabaseError, DBAPIError):
                # if we cannot connect to backend DB, skip api key check
                skip_check = True
                self.raven_client.captureException()
                bind_threadlocal(
                    api_key=api_key_text,
                    api_path=self.metric_path,
                    api_type=self.view_type,
                    api_key_db_fail=True,
                )

        if api_key is not None:
            valid_key = api_key.valid_key
            if api_key.allowed(self.view_type):
                self.log_count(valid_key)

                # Potentially avoid overhead of Redis connection.
                if self.ip_log_and_rate_limit:
                    if self.log_ip_and_rate_limited(valid_key, api_key.maxreq):
                        raise self.prepare_exception(DailyLimitExceeded())
            else:
                self.log_count("invalid")
                # Switch "invalid" with real key, add "api_key_allowed"
                bind_threadlocal(api_key=valid_key, api_key_allowed=False)

                if self.error_on_invalidkey:
                    raise self.prepare_exception(InvalidAPIKey())

        elif skip_check:
            pass
        else:
            if api_key_text is not None:
                self.log_count("invalid")
                bind_threadlocal(invalid_api_key=api_key_text)
            if self.error_on_invalidkey:
                raise self.prepare_exception(InvalidAPIKey())

        # If we failed to look up an ApiKey, create an empty one
        # rather than passing None through
        if api_key is None:
            api_key = Key()
        return self.view(api_key)
Exemplo n.º 3
0
 def check_response(self, response, status):
     self.assertEqual(response.content_type, 'application/json')
     self.assertEqual(response.charset, 'UTF-8')
     if status == 'ok':
         self.assertEqual(response.json, self.ip_response)
     elif status == 'invalid_key':
         self.assertEqual(response.json, InvalidAPIKey.json_body())
     elif status == 'not_found':
         self.assertEqual(response.json, self.not_found.json_body())
     elif status == 'parse_error':
         self.assertEqual(response.json, ParseError.json_body())
     elif status == 'limit_exceeded':
         self.assertEqual(response.json, DailyLimitExceeded.json_body())
Exemplo n.º 4
0
    def check(self):
        api_key = None
        api_key_text = self.parse_apikey()
        skip_check = False

        if api_key_text is None:
            self.log_count(None, False)
            if self.error_on_invalidkey:
                raise self.prepare_exception(InvalidAPIKey())

        if api_key_text is not None:
            try:
                session = self.request.db_session
                api_key = ApiKey.get(session, api_key_text)
            except Exception:
                # if we cannot connect to backend DB, skip api key check
                skip_check = True
                self.raven_client.captureException()

        if api_key is not None and api_key.allowed(self.view_type):
            self.log_count(api_key.valid_key, True)

            rate_key = 'apilimit:{key}:{path}:{time}'.format(
                key=api_key_text,
                path=self.metric_path,
                time=util.utcnow().strftime('%Y%m%d'))

            should_limit = rate_limit_exceeded(self.redis_client,
                                               rate_key,
                                               maxreq=api_key.maxreq)

            if should_limit:
                raise self.prepare_exception(DailyLimitExceeded())
        elif skip_check:
            pass
        else:
            if api_key_text is not None:
                self.log_count('invalid', False)
            if self.error_on_invalidkey:
                raise self.prepare_exception(InvalidAPIKey())

        # If we failed to look up an ApiKey, create an empty one
        # rather than passing None through
        api_key = api_key or ApiKey(valid_key=None,
                                    allow_fallback=False,
                                    allow_locate=True,
                                    allow_transfer=False,
                                    store_sample_locate=100,
                                    store_sample_submit=100)
        return self.view(api_key)
Exemplo n.º 5
0
 def check_response(self, response, status):
     self.assertEqual(response.content_type, 'application/json')
     self.assertEqual(response.charset, 'UTF-8')
     self.assertEqual(response.headers['Access-Control-Allow-Origin'], '*')
     self.assertEqual(response.headers['Access-Control-Max-Age'], '2592000')
     if status == 'ok':
         self.assertEqual(response.json, self.ip_response)
     elif status == 'invalid_key':
         self.assertEqual(response.json, InvalidAPIKey.json_body())
     elif status == 'not_found':
         self.assertEqual(response.json, self.not_found.json_body())
     elif status == 'parse_error':
         self.assertEqual(response.json, ParseError.json_body())
     elif status == 'limit_exceeded':
         self.assertEqual(response.json, DailyLimitExceeded.json_body())
Exemplo n.º 6
0
 def check_response(self, response, status):
     self.assertEqual(response.content_type, "application/json")
     self.assertEqual(response.charset, "UTF-8")
     self.assertEqual(response.headers["Access-Control-Allow-Origin"], "*")
     self.assertEqual(response.headers["Access-Control-Max-Age"], "2592000")
     if status == "ok":
         self.assertEqual(response.json, self.ip_response)
     elif status == "invalid_key":
         self.assertEqual(response.json, InvalidAPIKey.json_body())
     elif status == "not_found":
         self.assertEqual(response.json, self.not_found.json_body())
     elif status == "parse_error":
         self.assertEqual(response.json, ParseError.json_body())
     elif status == "limit_exceeded":
         self.assertEqual(response.json, DailyLimitExceeded.json_body())
Exemplo n.º 7
0
 def check_response(self, response, status):
     self.assertEqual(response.content_type, 'application/json')
     self.assertEqual(response.charset, 'UTF-8')
     self.assertEqual(response.headers['Access-Control-Allow-Origin'], '*')
     self.assertEqual(response.headers['Access-Control-Max-Age'], '2592000')
     if status == 'ok':
         self.assertEqual(response.json, self.ip_response)
     elif status == 'invalid_key':
         self.assertEqual(response.json, InvalidAPIKey.json_body())
     elif status == 'not_found':
         self.assertEqual(response.json, self.not_found.json_body())
     elif status == 'parse_error':
         self.assertEqual(response.json, ParseError.json_body())
     elif status == 'limit_exceeded':
         self.assertEqual(response.json, DailyLimitExceeded.json_body())
Exemplo n.º 8
0
 def check_response(self, data_queues, response, status):
     assert response.content_type == 'application/json'
     assert response.headers['Access-Control-Allow-Origin'] == '*'
     assert response.headers['Access-Control-Max-Age'] == '2592000'
     if status == 'ok':
         assert response.json == self.ip_response
     elif status == 'invalid_key':
         assert response.json == InvalidAPIKey.json_body()
     elif status == 'not_found':
         assert response.json == self.not_found.json_body()
     elif status == 'parse_error':
         assert response.json == ParseError.json_body()
     elif status == 'limit_exceeded':
         assert response.json == DailyLimitExceeded.json_body()
     if status != 'ok':
         self.check_queue(data_queues, 0)
Exemplo n.º 9
0
    def test_api_key_limit(self):
        london = self.geoip_data['London']
        api_key = uuid1().hex
        self.session.add(ApiKey(valid_key=api_key, maxreq=5, shortname='dis'))
        self.session.flush()

        # exhaust today's limit
        dstamp = util.utcnow().strftime('%Y%m%d')
        key = 'apilimit:%s:%s' % (api_key, dstamp)
        self.redis_client.incr(key, 10)

        res = self.app.post_json(
            '%s?key=%s' % (self.url, api_key), {},
            extra_environ={'HTTP_X_FORWARDED_FOR': london['ip']},
            status=403)
        self.assertEqual(res.content_type, 'application/json')
        self.assertEqual(res.json, DailyLimitExceeded.json_body())
Exemplo n.º 10
0
    def check(self):
        api_key = None
        api_key_text = self.request.GET.get('key', None)
        skip_check = False

        if api_key_text is None:
            self.log_count('none', False)
            if self.error_on_invalidkey:
                raise self.prepare_exception(InvalidAPIKey())

        if api_key_text is not None:
            try:
                session = self.request.db_ro_session
                api_key = session.query(ApiKey).get(api_key_text)
            except Exception:
                # if we cannot connect to backend DB, skip api key check
                skip_check = True
                self.raven_client.captureException()

        if api_key is not None:
            self.log_count(api_key.name, api_key.should_log(self.view_type))

            rate_key = 'apilimit:{key}:{path}:{time}'.format(
                key=api_key_text,
                path=self.metric_path,
                time=util.utcnow().strftime('%Y%m%d'))

            should_limit = rate_limit_exceeded(self.redis_client,
                                               rate_key,
                                               maxreq=api_key.maxreq)

            if should_limit:
                raise self.prepare_exception(DailyLimitExceeded())
        elif skip_check:
            pass
        else:
            if api_key_text is not None:
                self.log_count('invalid', False)
            if self.error_on_invalidkey:
                raise self.prepare_exception(InvalidAPIKey())

        # If we failed to look up an ApiKey, create an empty one
        # rather than passing None through
        api_key = api_key or ApiKey(valid_key=None)
        return self.view(api_key)
Exemplo n.º 11
0
 def check_response(self, data_queues, response, status, fallback=None):
     assert response.content_type == 'application/json'
     assert response.headers['Access-Control-Allow-Origin'] == '*'
     assert response.headers['Access-Control-Max-Age'] == '2592000'
     if status == 'ok':
         body = dict(response.json)
         if fallback:
             assert body['fallback'] == fallback
             del body['fallback']
         assert body == self.ip_response
     elif status == 'invalid_key':
         assert response.json == InvalidAPIKey.json_body()
     elif status == 'not_found':
         assert response.json == self.not_found.json_body()
     elif status == 'parse_error':
         assert response.json == ParseError.json_body()
     elif status == 'limit_exceeded':
         assert response.json == DailyLimitExceeded.json_body()
     if status != 'ok':
         self.check_queue(data_queues, 0)
Exemplo n.º 12
0
    def __call__(self):
        """Execute the view and return a response."""
        api_key = None
        api_key_text = self.parse_apikey()
        skip_check = False

        if api_key_text is None:
            self.log_count('none')
            if self.error_on_invalidkey:
                raise self.prepare_exception(InvalidAPIKey())

        if api_key_text is not None:
            try:
                api_key = get_key(self.request.db_session, api_key_text)
            except Exception:
                # if we cannot connect to backend DB, skip api key check
                skip_check = True
                self.raven_client.captureException()

        if api_key is not None and api_key.allowed(self.view_type):
            valid_key = api_key.valid_key
            self.log_count(valid_key)

            # Potentially avoid overhead of Redis connection.
            if self.ip_log_and_rate_limit:
                if self.log_ip_and_rate_limited(valid_key, api_key.maxreq):
                    raise self.prepare_exception(DailyLimitExceeded())

        elif skip_check:
            pass
        else:
            if api_key_text is not None:
                self.log_count('invalid')
            if self.error_on_invalidkey:
                raise self.prepare_exception(InvalidAPIKey())

        # If we failed to look up an ApiKey, create an empty one
        # rather than passing None through
        if api_key is None:
            api_key = Key()
        return self.view(api_key)