The use of services_error() isn't very consistent right now - the error messages ranges from short and not very descriptive messages to very long prints of all errors in eg. a failed node_save().

First of all I think services_error() should be replaced by the direct throwing of exceptions - I see no point in having a wrapper for throwing exceptions. Removing the wrapper would make it easier to follow the code.

Regarding the messages - the only place they are used in Services core are as "reason phrases" in the HTTP status lines. The HTTP specification specifies them as:

The Reason-Phrase is intended to give a short textual description of the Status-Code.

So if errors are encountered in the validation of a node - then the reason phrase should be something like "Validation failed" and not all of the error messages from the form - they would need to go into the response body instead.

Not all error messages are translated currently either and I'm quite unsure whether they should or shouldn't - but whatever we choose it should be the same for all error messages.

Comments

gdd’s picture

I'm fully in favor of doing this if we can make it happen quickly.

bsenftner’s picture

On this same issue, are the messages (first parameter) supposed to be wrapped in t() ? In the services/resources include files, some uses of services_error() wrap the messages in t() while most do not... what is correct?

gdd’s picture

Error codes are not translated currently, and I think they probably should be run through the translation system unless someone can come up with a reason why they shouldn't. Should we sanitize these strings too? Right now they are not being sanitized, and we shouldn't consider an submissions coming through services as being trustworthy (for instance, in the node resource we have

return services_error('Node type "'. $node->type .'" does not exist.', 406);

Which could be all sorts of problems depending on where it gets echoed. We can clean those when we run them through t()

kylebrowning’s picture

I think if we run everything through t() it will work.

voxpelli’s picture

I think we should translate the error messages but I think it should be up to the one catching the exception to escape them as we don't know if the message is going to be shown in an http header or in an html document.

gdd’s picture

StatusFileSize
new9.32 KB

OK so here is a patch that does the following:

- Pushes all errors through t()
- Properly tokenizes messages instead of just concatenating in data
- When we implode form_set_errors() arrays, consistently do it with '/n' (instead of sometimes doing it with ' ')
- Made many error messages more detailed and useful ('Comment @cid not found' instead of 'Comment not found')

It still doesn't address the original issue of how we use reason phrases and whether or not we should directly throw exceptions, but at least they are consistent.

gdd’s picture

Version: 7.x-3.0-beta2 » 7.x-3.x-dev
Status: Active » Needs review
StatusFileSize
new10.04 KB

voxpelli points out that using line returns in the messages will totally mess up http headers (where these are sometimes used) so I changed them to all use spaces.

kylebrowning’s picture

Patch looks great, have not tested it but does this affect Tests?

gdd’s picture

Status: Needs review » Needs work

OK I've committed this. Moving back to needs work so we can revisit for the issues voxpelli originally brought up

ygerasimov’s picture

Status: Needs work » Needs review
StatusFileSize
new2.63 KB

Tests get broken because of introduced

return services_error(implode(" "("\n", $errors), 406);

Fixed that in all resources.

kylebrowning’s picture

Version: 7.x-3.x-dev » 6.x-3.x-dev
Status: Needs review » Patch (to be ported)

Committed in 7.x please port to 6.x

kylebrowning’s picture

Status: Patch (to be ported) » Needs review
StatusFileSize
new1.3 KB

Heres the port to d6

kylebrowning’s picture

Status: Needs review » Fixed

Fixed and committed

voxpelli’s picture

Version: 6.x-3.x-dev » 7.x-3.x-dev
Status: Fixed » Needs work

Moving to "needs work" as heyrocker did in so we can revisit it for the issues I originally brought up here.

kylebrowning’s picture

how do send the error message in the body when using ServicesException class, or Exception for that matter. Do we do it the standard PHP way with header("Status: 500 Server Error"); and then the body is just printed?

rolf vreijdenberger’s picture

As long as headers are not set on the services level, it would all be fine.
A service should implement the setting of specific headers

In the case of the amfserver, http headers for errors should not be set since that is not the standard way of handling errors for the amf protocol, which is basically a protocol over the http protocol.
In the amfserver, the status codes (like 500, 401 etc) are not used for setting headers, though they can be used there for sending that info to the actionscript client.

tedbow’s picture

Status: Needs work » Needs review
StatusFileSize
new5.53 KB

I was running into a problem returning meaningful errors via a services call and I found this issue. Having all the errors from "form_get_errors" concatenated into one long string was not very useful to me.

I wrote a patch that adds an optional "data" parameter to the "services_error" function. Seems if this is part of the "ServicesException" constructor then you should be able to set it via "services_error".

I also added this to the calls of "services_error" that are results of form errors in resources . I am passing the resulting error array from "form_get_errors" to this arguments in "services_error".

I have also changed the way the REST server is handling exceptions throw from "services_controller_execute". I am catching "ServicesException" here, adding the headers as before but also passing errors from ServicesException::getData on to the formatter so that they can be displayed in the body.

kylebrowning’s picture

Status: Needs review » Needs work

this breaks a bunch of tests but i like where this is going for sure.

tedbow’s picture

kylebrowning, I ran all the Services tests locally on this and they all passed for me but I am new to Drupal's testing. Should I be running all of the site's tests?

tedbow’s picture

While I figure out the test issues I have made some changes to the patch.

I have added info about types of errors:

if ($errors = form_get_errors()) {
    return services_error(implode(" ", $errors), 406, array('form_errors' => $errors));
  }

I also the ability to alter the errors in the rest_server:

try {
    $server = new RESTServer();
    return $server->handle($canonical_path, $endpoint_path);
  }
  catch (Exception $e) {
    $server->handleException($e);
  }

In my case I need to alter the error output to the application calling the Rest Server expects.

kylebrowning’s picture

tests are passing, this looks good.

tedbow’s picture

I guess the alter was actually not in my last patch

-    $result = services_controller_execute($controller, $arguments);
+    try {
+      $result = services_controller_execute($controller, $arguments);
+    } catch (ServicesException $e) {
+      $errors = $this->handleException($e);
+      drupal_alter('rest_server_exectue_errors', $errors, $controller, $arguments);
+      $result = $errors;
+    }
kylebrowning’s picture

Version: 7.x-3.x-dev » 6.x-3.x-dev
Status: Needs work » Patch (to be ported)

Patch in #22 needs to be ported to 6.x

kylebrowning’s picture

Status: Patch (to be ported) » Fixed

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.