jsonresponse: add x-error-code header in case of error (#89784)
gitea/passerelle/pipeline/head This commit looks good Details

This commit is contained in:
Emmanuel Cazenave 2024-04-19 12:25:27 +02:00
parent c25a371c10
commit 38d62092ef
2 changed files with 49 additions and 3 deletions

View File

@ -93,7 +93,7 @@ class to_json:
response.update(err.extra_dict)
return response
def render_data(self, req, data, status=200):
def render_data(self, req, data, status=200, headers=None):
debug = DEFAULT_DEBUG
debug = debug or req.GET.get('debug', 'false').lower() in ('true', 't', '1', 'on')
debug = debug or req.GET.get('decode', '0').lower() in ('true', 't', '1', 'on')
@ -116,7 +116,9 @@ class to_json:
plain = '%s(%s);' % (jsonp_cb, plain)
content_type = 'application/javascript'
return HttpResponse(plain, content_type='%s; charset=UTF-8' % content_type, status=status)
return HttpResponse(
plain, content_type='%s; charset=UTF-8' % content_type, status=status, headers=headers
)
def api_func(self, f, *args, **kwargs):
return self.api(f, args[0], *args, **kwargs)
@ -176,6 +178,7 @@ class to_json:
data = self.err_to_response(e)
if getattr(e, 'err_code', None):
data['err'] = e.err_code
headers = {'x-error-code': data['err']}
if getattr(e, 'http_status', None):
status = e.http_status
elif isinstance(e, (ObjectDoesNotExist, Http404)):
@ -185,7 +188,7 @@ class to_json:
else:
status = self.error_code
response = self.render_data(req, data, status)
response = self.render_data(req, data, status, headers)
# We preempt Django logging of HTTP responses to prevent it from
# logging our 500 responses as errors.

View File

@ -33,6 +33,7 @@ from passerelle.apps.mdel.models import MDEL
from passerelle.base.models import BaseResource, LoggingParameters, ProxyLogger, ResourceLog, ResourceStatus
from passerelle.contrib.stub_invoices.models import StubInvoicesConnector
from passerelle.utils.api import endpoint
from passerelle.utils.jsonresponse import APIError
from tests.test_manager import login
@ -1094,3 +1095,45 @@ def test_view_connector(db, app, monkeypatch, admin_user):
with patch_init, patch_object:
response = app.get(url)
assert len(response.pyquery('#description')) == 1
class DummyErrorConnector(BaseResource):
class Meta:
app_label = 'dummy-error'
@endpoint(perm='OPEN')
def error(self, request):
raise APIError('error')
@endpoint(perm='OPEN')
def noerror(self, request):
return {'data': 1}
def test_dummy_error_connector(db, app):
connector = DummyErrorConnector()
connector.id = 42
url_error = reverse(
'generic-endpoint',
kwargs={
'connector': 'foo',
'slug': 'foo',
'endpoint': 'error',
},
)
url_noerror = reverse(
'generic-endpoint',
kwargs={
'connector': 'foo',
'slug': 'foo',
'endpoint': 'noerror',
},
)
patch_init = mock.patch('passerelle.views.GenericConnectorMixin.init_stuff')
patch_object = mock.patch('passerelle.views.GenericEndpointView.get_object', return_value=connector)
with patch_init, patch_object:
response = app.get(url_error)
assert response.headers['x-error-code'] == '1'
response = app.get(url_noerror)
assert 'x-error-code' not in response.headers