def _assert_failure(self, view, request, status_code, error_code, exception): middleware = OVSMiddleware() with self.assertRaises(exception) as context: view(request) response = middleware.process_exception(request, context.exception) self.assertEqual(response.status_code, status_code) data = json.loads(response.content) self.assertIn('error', data) self.assertEqual(data['error'], error_code)
def test_ratelimit(self): """ Validates whether the rate limiter behaves correctly """ from api.oauth2.decorators import limit, auto_response @auto_response() @limit(amount=2, per=2, timeout=2) def the_function(input_value, *args, **kwargs): """ Decorated function """ _ = args, kwargs output['value'] = input_value return input_value output = {'value': None} request = self.factory.post('/') with self.assertRaises(KeyError): # Should raise a KeyError complaining about the HTTP_X_REAL_IP the_function(1, request) request.META['HTTP_X_REAL_IP'] = '127.0.0.1' response = the_function(2, request) self.assertEqual(output['value'], 2) self.assertEqual(response.status_code, 200) self.assertEqual(response.content, '2') response = the_function(3, request) self.assertEqual(output['value'], 3) self.assertEqual(response.status_code, 200) self.assertEqual(response.content, '3') with self.assertRaises(HttpTooManyRequestsException) as context: the_function(4, request) response = OVSMiddleware().process_exception(request, context.exception) self.assertEqual(output['value'], 3) self.assertEqual(response.status_code, 429) self.assertEqual( json.loads(response.content)['error'], 'rate_limit_reached') with self.assertRaises(HttpTooManyRequestsException) as context: the_function(5, request) response = OVSMiddleware().process_exception(request, context.exception) self.assertEqual(output['value'], 3) self.assertEqual(response.status_code, 429) self.assertEqual( json.loads(response.content)['error'], 'rate_limit_timeout') time.sleep(5) response = the_function(6, request) self.assertEqual(output['value'], 6) self.assertEqual(response.status_code, 200) self.assertEqual(response.content, '6')
def relay(*args, **kwargs): """ Relays any call to another node. Assume this example: * A user wants to execute a HTTP GET on /api/storagerouters/ ** /api/<call> * He'll have to execute a HTTP GET on /api/relay/<call> ** This will translate to /apt/relay/storagerouters/ Parameters: * Mandatory: ip, port, client_id, client_secret * All other parameters will be passed through to the specified node """ @authenticated() @required_roles(['read']) @load() def _relay(_, ip, port, client_id, client_secret, raw_version, request): path = '/{0}'.format(request.path.replace('/api/relay/', '')) method = request.META['REQUEST_METHOD'].lower() client = OVSClient(ip, port, credentials=(client_id, client_secret), version=raw_version, raw_response=True) if not hasattr(client, method): raise HttpBadRequestException( error='unavailable_call', error_description='Method not available in relay') client_kwargs = {'params': request.GET} if method != 'get': client_kwargs['data'] = request.POST call_response = getattr(client, method)(path, **client_kwargs) response = HttpResponse(call_response.text, content_type='application/json', status=call_response.status_code) for header, value in call_response.headers.iteritems(): response[header] = value response['OVS-Relay'] = '{0}:{1}'.format(ip, port) return response try: return _relay(*args, **kwargs) except Exception as ex: if OVSMiddleware.is_own_httpexception(ex): return HttpResponse(ex.data, status=ex.status_code, content_type='application/json') message = str(ex) status_code = 400 if hasattr(ex, 'detail'): message = ex.detail if hasattr(ex, 'status_code'): status_code = ex.status_code logger = LogHandler.get('api', name='metadata') logger.exception('Error relaying call: {0}'.format(message)) return HttpResponse(json.dumps({ 'error_descirption': message, 'error': 'relay_error' }), content_type='application/json', status=status_code)
def relay(*args, **kwargs): """ Relays any call to another node. Assume this example: * A user wants to execute a HTTP GET on /api/storagerouters/ ** /api/<call> * He'll have to execute a HTTP GET on /api/relay/<call> ** This will translate to /apt/relay/storagerouters/ Parameters: * Mandatory: ip, port, client_id, client_secret * All other parameters will be passed through to the specified node """ @authenticated() @required_roles(['read']) @load() def _relay(_, ip, port, client_id, client_secret, raw_version, request): path = '/{0}'.format(request.path.replace('/api/relay/', '')) method = request.META['REQUEST_METHOD'].lower() client = OVSClient(ip, port, credentials=(client_id, client_secret), version=raw_version, raw_response=True) if not hasattr(client, method): raise HttpBadRequestException(error='unavailable_call', error_description='Method not available in relay') client_kwargs = {'params': request.GET} if method != 'get': client_kwargs['data'] = request.POST call_response = getattr(client, method)(path, **client_kwargs) response = HttpResponse(call_response.text, content_type='application/json', status=call_response.status_code) for header, value in call_response.headers.iteritems(): response[header] = value response['OVS-Relay'] = '{0}:{1}'.format(ip, port) return response try: return _relay(*args, **kwargs) except Exception as ex: if OVSMiddleware.is_own_httpexception(ex): return HttpResponse(ex.data, status=ex.status_code, content_type='application/json') message = str(ex) status_code = 400 if hasattr(ex, 'detail'): message = ex.detail if hasattr(ex, 'status_code'): status_code = ex.status_code logger = LogHandler.get('api', name='metadata') logger.exception('Error relaying call: {0}'.format(message)) return HttpResponse(json.dumps({'error_descirption': message, 'error': 'relay_error'}), content_type='application/json', status=status_code)