Welcome | Get started | Dive | Contribute | Topics | Reference | Changes | More
Answering to invalid requests¶
This document contains code snippets (lines starting with >>>
) that get
tested as part of our development workflow.
>>> from lino import startup
>>> startup('lino_book.projects.min2.settings.doctests')
>>> from lino.api.doctest import *
The following request caused a traceback
type object 'AnonymousUser' has no attribute 'get_chooser_for_field'
rather than responding PermissionDenied:
>>> url = '/api/users/Me/2?dm=detail&fmt=json&ul=en&wt=d'
>>> res = test_client.get(url)
Forbidden (Permission denied): /api/users/Me/2
Traceback (most recent call last):
...
django.core.exceptions.PermissionDenied: No permission to run TableRequest My settings on users.Me
>>> res.status_code
403
Lino currently returns HTML content even though fmt=json
has been requested:
>>> print(res.content.decode())
<!doctype html>
<html lang="en">
<head>
<title>403 Forbidden</title>
</head>
<body>
<h1>403 Forbidden</h1><p></p>
</body>
</html>
TODO: return JSON content rather than HTML
Non-anonymous requests¶
We are going to send some invalid AJAX requests to
lino_xl.lib.contacts.RolesByPerson
, a slave table on
person.
>>> contacts.RolesByPerson.master
<class 'lino_xl.lib.contacts.models.Person'>
Simulate an AJAX request:
>>> headers = dict(HTTP_X_REQUESTED_WITH='XMLHttpRequest')
>>> headers.update(REMOTE_USER='robin')
>>> test_client.force_login(rt.login('robin').user)
Here is a valid request:
>>> url = "/api/contacts/RolesByPerson?fmt=json&start=0&limit=15&mt=8&mk=114"
>>> res = test_client.get(url, **headers)
>>> print(res.status_code)
200
>>> d = AttrDict(json.loads(res.content.decode()))
>>> d.count
1
>>> print(d.title)
Mr Hans Altenberg is contact person for
Specifying an invalid primary key for the master (5114 in the example below) will internally raise an ObjectDoesNotExist exception, which in turn will cause an HttpResponseBadRequest response (i.e. status code 400):
>>> import logging
>>> logger = logging.getLogger("django.request")
>>> logger.setLevel(logging.CRITICAL)
>>> settings.SITE.strict_master_check = True
>>> url = "/api/contacts/RolesByPerson?fmt=json&start=0&limit=15&mt=8&mk=114114"
>>> res = test_client.get(url, **headers)
AjaxExceptionResponse BadRequest: MissingRow(Person matching query does not exist. (pk=114114))
in request GET /api/contacts/RolesByPerson?fmt=json&start=0&limit=15&mt=8&mk=114114
TRACEBACK:
...
>>> url = "/api/contacts/RolesByPerson?fmt=json&start=0&limit=15&mt=8&mk=foo"
>>> res = test_client.get(url, **headers)
AjaxExceptionResponse BadRequest: MissingRow(Field 'id' expected a number but got 'foo'. (pk=foo))
in request GET /api/contacts/RolesByPerson?fmt=json&start=0&limit=15&mt=8&mk=foo
TRACEBACK:
...
Since RolesByPerson has a known master class (i.e. Person), the mt
url parameter is ignored: an invalid value for mt
does not
raise an exception:
>>> url = "/api/contacts/RolesByPerson?fmt=json&start=0&limit=15&mt=8888&mk=114"
>>> res = test_client.get(url, **headers)
>>> print(res.status_code)
200
Request data not supplied¶
After 20170410 the following AJAX request no longer raises a real exception but
continues to log it. Raising an exception had the disadvantage of having an
email sent to the ADMINS
, which was just disturbing and not helpful
because it had no “request data supplied”. Now the end user gets an
appropriate message because it receives a status code 400.
>>> url = '/api/cal/EventsByProject?_dc=1491615952104&fmt=json&rp=ext-comp-1306&start=0&limit=15&mt=13&mk=188'
>>> res = test_client.get(url, **headers)
AjaxExceptionResponse Http404: cal.EventsByProject is not a class
in request GET /api/cal/EventsByProject?_dc=1491615952104&fmt=json&rp=ext-comp-1306&start=0&limit=15&mt=13&mk=188
TRACEBACK:
...
>>> res.status_code
400
>>> #print(json.loads(res.content)['message'])
>>> print(res.content.decode())
Http404: cal.EventsByProject is not a class