How to globally handle HTTP errors in Grails (status codes 4xx/5xx)? - grails

Is there a way in Grails to catch all the possible HTTP errors before they're being sent to the client browser, as to be able to handle the content being sent to the client? I mean all 4xx and 5xx HTTP status codes, not only the 403, 404 and 500 like other have suggested.
What I'd like to do is to catch all HTTP errors in the first place, without having to specify them all one by one, then in a second step I would filter (e.g. in an error controller) specific error codes that I would like to handle (e.g. 400), but at least the ones that I would not specify would render to a generic error template I defined.
If this can't be done (or shouldn't be done), which HTTP errors codes should really be checked for and handled? I can at least see those codes happening at some point: 400, 401, 403, 404, 405, 500, 501, 503. And also, how should they be handled, using HTTP response codes mappings?
Thanks!

haven't actually tried it but maybe a number constraint might work?
"$errorCode" {
controller = "errors"
action = "displayError"
constraints {
errorCode(matches:/\d{3}/)
}
}

Related

Swashbuckle refuses to show response example for HTTP 500

I'm using Swashbuckle for a web api app in .Net Core 3.1. I want response examples for various response codes. I can get all of them working except HTTP 500. These are the attributes on the a particular method:
[SwaggerRequestExample(typeof(GroupInfoRequest), typeof(GroupInfoRequestExample))]
[SwaggerResponseExample(Status200OK, typeof(GroupInfo200Example))]
[SwaggerResponseExample(Status400BadRequest, typeof(GroupInfo400Example))]
[SwaggerResponseExample(Status403Forbidden, typeof(GroupInfo403Example))]
[SwaggerResponseExample(Status404NotFound, typeof(GroupInfo404Example))]
[SwaggerResponseExample(Status500InternalServerError, typeof(GroupInfo500Example))]
[ProducesResponseType(Status200OK)]
[ProducesResponseType(Status400BadRequest)]
[ProducesResponseType(Status403Forbidden)]
[ProducesResponseType(Status404NotFound)]
[ProducesResponseType(Status500InternalServerError)]
I can get all of them to render except the GroupInfo500Example. The application only returns an HTTP 500 to indicate an internal exception that isn't caught by other exception handlers. It is intended to return a body that contains, among other things, a GUID that can be passed in to our support organization to help them look up the exception in the application logs. I can not get the example to render for any 5xx error. If I change it to another status code, it renders, so it's specifically the 5xx result that doesn't render. I've checked the openapi json produced and it's not produced as part of the generated JSON. Is there a filter in place that keeps 5xx response docs from showing response examples?
Finally figured it out. I was missing part of the 'ProducesResponseType' attribute. It needs to have the return type as well as the HTTP status code. This works:
[ProducesResponseType(typeof(ADServiceOperationMultipleResult<GroupActionRequestForUsers, UserQuery>), Status200OK)]
[ProducesResponseType(typeof(ADServiceOperationMultipleResult<GroupActionRequestForUsers, UserQuery>), Status400BadRequest)]
[ProducesResponseType(typeof(ADServiceOperationMultipleResult<GroupActionRequestForUsers, UserQuery>), Status403Forbidden)]
[ProducesResponseType(typeof(ADServiceOperationMultipleResult<GroupActionRequestForUsers, UserQuery>), Status404NotFound)]
[ProducesResponseType(typeof(ADServiceOperationMultipleResult<GroupActionRequestForUsers, UserQuery>), Status422UnprocessableEntity)]
[ProducesResponseType(typeof(ADServiceOperationMultipleResult<GroupActionRequestForUsers, UserQuery>), Status500InternalServerError)]
Oddly enough, some status codes were including the example without it, but now the examples appear consistently as long as I include the method return type in the attribute.

The method presentations.batchUpdate throws "Internal error encountered"

I'm working on generation of Google Presentation and sometimes batchUpdate throws the error:
{
"error": {
"code": 500,
"message": "Internal error encountered.",
"status": "INTERNAL"
}
}
Here's the example of the request body
Issue:
Your request body is huge. You are requesting many updates in the presentation with a single call. Since you are getting a 500 error, the server is most likely having problems while processing this huge amount of requests.
It's certainly not a question of write request limits, since you are only making one single (large) write request (and HTTP status is not the appropriate one either).
Solution:
In any case, I would suggest you to split your call into as many parts as necessary so that you never get this error. Group the requests into different request bodies and call batchUpdate several successive times. This should fix your problem.
Reference:
presentations.batchUpdate
Slides API: Usage Limits
500 Internal Server Error

how to add a status message on a grails respond

I have created a method that is called after every uncatched exception and respond a gson view:
void handleError(){
respond([status: 500, view: "/customErr"], [
code : 500,
message : "whatever internal error",
])
}
this works fine but the main problem that I have is that my client (another server acting as client) is receiving a http response with a 500 status but the status message is null. I've checked the respond docs and I don't see a property message or something.
this if what my client receive:
wslite.rest.RESTClientException: 500 null
and that null is the response's status message that is not set by grails
How can I add a detail message on my respond? idyllically something like this:
respond([status: 500, statusMessage: "my custom
message", view: "/customErr"], [
code : 500,
message : "whatever internal error",
])
grails uses Servlet API’s HttpServletResponse to build response.
now check the java doc for HttpServletResponse class.
there are only 2 methods to define status message:
void setStatus(int sc, String msg) Deprecated. As of version 2.1, due to ambiguous meaning of the message parameter. To set a status code use setStatus(int), to send an error with a description use sendError(int, String).
void sendError(int sc, String msg) Sends an error response to the client using the specified status and clears the buffer. The server defaults to creating the response to look like an HTML-formatted server error page containing the specified message, setting the content type to "text/html".
The first one is deprecated. The second one sends the status message, but it will not send the body - mainly this used for fatal errors...
So, officially by servlet documentation there is no way to send both: message and body in response.
The question is tricky. Because according to Apache Tomcat the "custom status message" feature will be removed starting from version 9: https://tomcat.apache.org/tomcat-8.5-doc/config/systemprops.html#Other
But according to RFC2616 sec 6.1.1 : The reason phrases listed here are only recommendations -- they MAY be replaced by local equivalents without affecting the protocol.
This doesn't directly answer your question, and may not solve your issue depending on how much control you have over the application that receives the error, but you can add error messages to the header of the response which should pass through to the client (if it knows to check for them).
String errorMessage = "Whatever Internal Server Error"
response.addHeader("custom-error", errorMessage)
response.sendError(500, errorMessage)
That'll send the message in the header and as the response message... I do not know if this works with respond() or how that interacts with the response object in the controller... but if you're responding to render a view as the error page, you should be able to add the message to the model included in the respond() call and show that on the error page (at least, I'd think so).

What the name of the error domain for HTTP error codes?

I have some network code which behaves differently if an error is due to timeout, bad url, url not found etc, etc. which are all covered by NSURLErrorDomain.
However if I get a http error, such as http 406, then that's not in NSURLErrorDomain. The domain is "HTTP Error", but I don't want to use that as a hardcoded string, I want to use whatever its NSWhateverErrorDomain definition is, but after loads of searching I just can't find what that is anywhere.
Undocumented NSURLErrorDomain error codes (-1001, -1003 and -1004) using StoreKit
Reference:
https://developer.apple.com/reference/cfnetwork/cfnetworkerrors

Are all elements in a POST requests body mandatory?

If a POST request requires that i send four data elements in the body, like:
{
"name":abc,
"surname":xyz,
"contact_no":1234,
"address":random_value
}
What will happen if I miss out some of the elements, for example if I call the web service with elements like,
{
"name":abc,
"surname":xyz,
}
What error is the server likely to throw ? I am having this issue because I am making a API call and it's giving me a HTTP error 500, so I guess it's not an error on my part, but this is one doubt i wanted to clear. Thanks in advance.
Its depends on the service structure (if all fields are mandatory or not),
and HTTP error (500) returns to server error or (server or link) not found .

Resources