Problem/Motivation
If an exception or other error is thrown during an AJAX operation, the end user receives an alert dialog with an error message, and a fair amount of diagnostic information. This is great for a development environment. However, it's possible in a production environment, that a sysadmin might not want this information exposed to end users. (I've bracketed out and bold-faced the potentially dangerous information).
Here is an example of an alert dialog i get if I create a flaky db connection in my back end during an autocomplete session.
An AJAX HTTP error occurred.
HTTP Result Code: 500
Debugging information follows.
Path: https://drupal7.dev.instance.local/taxonomy/autocomplete/field_ugc_colle...
StatusText: Service unavailable (with message)
ResponseText: PDOException: SQLSTATE[28000] [1045] Access denied for user '[db username]'@'[DB HOST]' [(using password: YES)] in lock_may_be_available() ([line 164 of /path/to/application/code/docroot/includes/lock.inc]).
Proposed resolution
Regular exception handling (to the browser window) consults the value of the error_displayable() function before rendering an error the client.
<?php
if (error_displayable($error)) {
// more logic to determine what/how to render error
?>
However, the AJAX error part of the function does not consult error_displayable(). It only checks if the error is fatal.
<?php
if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') {
if ($fatal) {
// When called from JavaScript, simply output the error message.
print t('%type: !message in %function (line %line of %file).', $error);
?>
My patch would change the AJAX error handling part of _drupal_log_error() to also consult the return value of error_displayable(), changing
<?php
if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') {
if ($fatal) {
// When called from JavaScript, simply output the error message.
print t('%type: !message in %function (line %line of %file).', $error);
?>
to
<?php
if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') {
if ($fatal) {
if (error_displayable($error)) {
// When called from JavaScript, simply output the error message.
print t('%type: !message in %function (line %line of %file).', $error);
}
exit;
}
?>
Remaining tasks
Discuss. Critique. Review. Test, please. One thing I'm not happy with is that the header still says: Service unavailable (with message) in the xmlhttp request, rather than just Service unavailable.
User interface changes
None.
API changes
None.