def test_etag_check_etag(self, app, schemas): etag_schema = schemas.DocEtagSchema old_item = {'item_id': 1, 'db_field': 0} new_item = {'item_id': 1, 'db_field': 1} old_etag = _generate_etag(old_item) old_etag_with_schema = _generate_etag(old_item, etag_schema) with app.test_request_context('/', headers={'If-Match': old_etag}): check_etag(old_item) if is_etag_enabled(app): with pytest.raises(PreconditionFailed): check_etag(new_item) else: check_etag(new_item) disable_etag_for_request() check_etag(old_item) check_etag(new_item) with app.test_request_context( '/', headers={'If-Match': old_etag_with_schema}): check_etag(old_item, etag_schema) if is_etag_enabled(app): with pytest.raises(PreconditionFailed): check_etag(new_item, etag_schema) else: check_etag(new_item) disable_etag_for_request() check_etag(old_item) check_etag(new_item)
def test_etag_set_etag(self, app, schemas): etag_schema = schemas.DocEtagSchema item = {'item_id': 1, 'db_field': 0} etag = _generate_etag(item) etag_with_schema = _generate_etag(item, etag_schema) with app.test_request_context('/'): set_etag(item) if is_etag_enabled(app): assert _get_etag_ctx()['etag'] == etag del _get_etag_ctx()['etag'] else: assert 'etag' not in _get_etag_ctx() disable_etag_for_request() set_etag(item) assert 'etag' not in _get_etag_ctx() with app.test_request_context('/', headers={'If-None-Match': etag}): if is_etag_enabled(app): with pytest.raises(NotModified): set_etag(item) else: set_etag(item) assert 'etag' not in _get_etag_ctx() disable_etag_for_request() set_etag(item) assert 'etag' not in _get_etag_ctx() with app.test_request_context( '/', headers={'If-None-Match': etag_with_schema}): if is_etag_enabled(app): with pytest.raises(NotModified): set_etag(item, etag_schema) else: set_etag(item, etag_schema) assert 'etag' not in _get_etag_ctx() disable_etag_for_request() set_etag(item, etag_schema) assert 'etag' not in _get_etag_ctx() with app.test_request_context('/', headers={'If-None-Match': 'dummy'}): if is_etag_enabled(app): set_etag(item) assert _get_etag_ctx()['etag'] == etag del _get_etag_ctx()['etag'] set_etag(item, etag_schema) assert _get_etag_ctx()['etag'] == etag_with_schema del _get_etag_ctx()['etag'] else: set_etag(item) assert 'etag' not in _get_etag_ctx() set_etag(item, etag_schema) assert 'etag' not in _get_etag_ctx() disable_etag_for_request() set_etag(item) assert 'etag' not in _get_etag_ctx() set_etag(item, etag_schema) assert 'etag' not in _get_etag_ctx()
def test_etag_set_etag_in_response(self, app, schemas, paginate): etag_schema = schemas.DocEtagSchema item = {'item_id': 1, 'db_field': 0} extra_data = ('Dummy pagination header', ) if paginate else tuple() etag = _generate_etag(item, extra_data=extra_data) etag_with_schema = _generate_etag(item, etag_schema, extra_data=extra_data) with app.test_request_context('/'): resp = Response() if extra_data: resp.headers['X-Pagination'] = 'Dummy pagination header' if is_etag_enabled(app): set_etag_in_response(resp, item, None) assert resp.get_etag() == (etag, False) set_etag_in_response(resp, item, etag_schema) assert resp.get_etag() == (etag_with_schema, False) else: set_etag_in_response(resp, item, None) assert resp.get_etag() == (None, None) set_etag_in_response(resp, item, etag_schema) assert resp.get_etag() == (None, None) disable_etag_for_request() resp = Response() set_etag_in_response(resp, item, None) assert resp.get_etag() == (None, None) set_etag_in_response(resp, item, etag_schema) assert resp.get_etag() == (None, None)
def test_etag_verify_check_etag_warning(self, app, method): old_item = {'item_id': 1, 'db_field': 0} old_etag = _generate_etag(old_item) with mock.patch.object(app.logger, 'warning') as mock_warning: with app.test_request_context('/', method=method, headers={'If-Match': old_etag}): verify_check_etag() if (is_etag_enabled(app) and method in ['PUT', 'PATCH', 'DELETE']): assert mock_warning.called mock_warning.reset_mock() else: assert not mock_warning.called check_etag(old_item) verify_check_etag() assert not mock_warning.called disable_etag_for_request() verify_check_etag() assert not mock_warning.called check_etag(old_item) verify_check_etag() assert not mock_warning.called
def test_etag_is_etag_enabled_for_request(self, app): with app.test_request_context('/'): assert ( is_etag_enabled_for_request() == is_etag_enabled(current_app)) disable_etag_for_request() assert not is_etag_enabled_for_request()
def test_etag_check_precondition(self, app, method): with app.test_request_context('/', method=method): if method in ['PUT', 'PATCH', 'DELETE'] and is_etag_enabled(app): with pytest.raises(PreconditionRequired): check_precondition() else: check_precondition() disable_etag_for_request() check_precondition()
def test_etag_verify_check_etag_exception(self, app, method, debug, testing): app.config['DEBUG'] = debug app.config['TESTING'] = testing with NoLoggingContext(app): with app.test_request_context('/', method=method): if ((debug or testing) and is_etag_enabled(app) and method in ['PUT', 'PATCH', 'DELETE']): with pytest.raises( CheckEtagNotCalledError, match='ETag enabled but not checked in endpoint'): verify_check_etag() else: verify_check_etag()
def test_etag_operations_etag_disabled(self, app_with_etag): client = app_with_etag.test_client() assert not is_etag_enabled(app_with_etag) # GET without ETag: OK response = client.get('/test/') assert response.status_code == 200 # GET with whatever ETag: OK (dummy ETag ignored) response = client.get('/test/', headers={'If-None-Match': 'dummy_etag'}) assert response.status_code == 200 # POST item_1 item_1_data = {'field': 0} response = client.post('/test/', data=json.dumps(item_1_data), content_type='application/json') assert response.status_code == 201 item_1_id = response.json['item_id'] # GET by ID: OK response = client.get('/test/{}'.format(item_1_id)) assert response.status_code == 200 # GET by ID with whatever ETag: OK (dummy ETag ignored) response = client.get('/test/{}'.format(item_1_id), headers={'If-None-Match': 'dummy_etag'}) assert response.status_code == 200 # PUT without ETag: OK item_1_data['field'] = 1 response = client.put('/test/{}'.format(item_1_id), data=json.dumps(item_1_data), content_type='application/json') assert response.status_code == 200 # PUT with whatever ETag: OK (dummy ETag ignored) item_1_data['field'] = 2 response = client.put('/test/{}'.format(item_1_id), data=json.dumps(item_1_data), content_type='application/json') assert response.status_code == 200 # POST item_2 item_2_data = {'field': 9} response = client.post('/test/', data=json.dumps(item_2_data), content_type='application/json') assert response.status_code == 201 item_2_id = response.json['item_id'] # DELETE without ETag: No Content (dummy ETag ignored) response = client.delete('/test/{}'.format(item_1_id)) assert response.status_code == 204 # DELETE with whatever ETag: No Content (dummy ETag ignored) response = client.delete('/test/{}'.format(item_2_id), headers={'If-Match': 'dummy_etag'}) assert response.status_code == 204
def test_etag_operations_etag_enabled(self, app_with_etag): client = app_with_etag.test_client() assert is_etag_enabled(app_with_etag) # GET without ETag: OK response = client.get('/test/') assert response.status_code == 200 list_etag = response.headers['ETag'] # GET with correct ETag: Not modified response = client.get('/test/', headers={'If-None-Match': list_etag}) assert response.status_code == 304 # POST item_1 item_1_data = {'field': 0} response = client.post('/test/', data=json.dumps(item_1_data), content_type='application/json') assert response.status_code == 201 item_1_id = response.json['item_id'] # GET with wrong/outdated ETag: OK response = client.get('/test/', headers={'If-None-Match': list_etag}) assert response.status_code == 200 # GET by ID without ETag: OK response = client.get('/test/{}'.format(item_1_id)) assert response.status_code == 200 item_etag = response.headers['ETag'] # GET by ID with correct ETag: Not modified response = client.get('/test/{}'.format(item_1_id), headers={'If-None-Match': item_etag}) assert response.status_code == 304 # PUT without ETag: Precondition required error item_1_data['field'] = 1 response = client.put('/test/{}'.format(item_1_id), data=json.dumps(item_1_data), content_type='application/json') assert response.status_code == 428 # PUT with correct ETag: OK response = client.put('/test/{}'.format(item_1_id), data=json.dumps(item_1_data), content_type='application/json', headers={'If-Match': item_etag}) assert response.status_code == 200 new_item_etag = response.headers['ETag'] # PUT with wrong/outdated ETag: Precondition failed error item_1_data['field'] = 2 response = client.put('/test/{}'.format(item_1_id), data=json.dumps(item_1_data), content_type='application/json', headers={'If-Match': item_etag}) assert response.status_code == 412 # GET by ID with wrong/outdated ETag: OK response = client.get('/test/{}'.format(item_1_id), headers={'If-None-Match': item_etag}) assert response.status_code == 200 # DELETE without ETag: Precondition required error response = client.delete('/test/{}'.format(item_1_id)) assert response.status_code == 428 # DELETE with wrong/outdated ETag: Precondition failed error response = client.delete('/test/{}'.format(item_1_id), headers={'If-Match': item_etag}) assert response.status_code == 412 # DELETE with correct ETag: No Content response = client.delete('/test/{}'.format(item_1_id), headers={'If-Match': new_item_etag}) assert response.status_code == 204