REST API best practice on handling errors [closed] - rest

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
I'm wondering how should errors be handled on a REST API backend, internally. Say the user gives an incomplete request payload, fails validation, or looking for something that does not exist. We'll want to return 400 or 404 for those cases.
In some frameworks (only those that I have experience with), we do this by throwing exceptions (NestJS, Spring, etc). But on Go, there's the error returned by operation methods (validation, access to db) that can indicate the error (if err != nil) and we can bubble-up the err up to the controller level and have different handling for it (return some specific status, error message, etc).
My question is, which way (or if there's another preferred way) is the best to handle errors on a backend? The problem is throwing exceptions will show on any logs monitoring tools and will show that the app have so many errors even though most might be 4XX errors (we could filter the logs to find 50X errors definitely), and using the errors return object might be cumbersome to bubble-up for every validation functions we'd have. I'll be happy if there's any repository example or article that explains the similar topic.
Thanks!

One issue I see with throwing exceptions is that we may give out some internal error to the users, which may not benefit them and will also expose our implementation.
using the errors return object might be cumbersome to bubble-up for every validation functions we'd have.
Yes propagating the error can be cumbersome, but I think that it is good to propagate required errors from the called function to the callee and let the callee decide what they want to do. For the rest call, I think it is ok if we propagate the error from the DB layer to the service layer to the rest layer.
Also, we can wrap the error at the rest layer into a standard response message
{
"type": "/errors/incorrect-user-pass",
"title": "Incorrect username or password.",
"status": 401,
"detail": "Authentication failed due to incorrect username or password.",
"instance": "/login/log/abc123"
}
We can do this by calling a wrapper function for handling error when we call Http.Handle(). This post contains example function ServeHTTP().
Credit: The serveHTTP function was taken from Zeynel Ă–zdemir and the response object example from https://www.baeldung.com/

Related

Error Handling in Scatter-Gather (Mule 4)

I have a question.
In an interview, I was asked if one of the routes of scatter-gather fail, will we get the output. I replied with a no as scatter-gather always gives a consolidated payload taken from all routes, and then they asked me if I still want to get the payload from the successful routes, what should I do -> I answered with Try scope and on-error continue. (I hope I was right here, please explain if I wasn't).
The next scenario they gave me was like this: If I have an on-error-propagate set for the scatter-gather and I also have a payload in that. So when the route fails and the handler comes to on-error-propagate, will the payload present there be printed or not. My answer to this question was a yes and I said that because on-error-propagate executes all its steps, the payload present inside its scope will be printed and then the flow will exit.
I don't know if that was right or not, so please help me with the correct answer for this scenario.
I'm not sure if this is the right platform for these question but I'll try to answer them.
I was asked if one of the routes of scatter-gather fail, will we get the output. I replied with a no as scatter-gather always gives a consolidated payload taken from all routes
Scatter-gather executes all routes simultaneously and generates a LinkedHashMap of all the Mule Events (not just payloads). The payload from each event can certainly be extracted or functions like flatten() can be used to flatten the contents linearly. If one of the routes fail and no error handling is done, an error object will be introduced and scatter-gather will fail.
they asked me if I still want to get the payload from the successful routes, what should I do -> I answered with Try scope and on-error continue.
Your answer seems good to me. Although, please note that on-error-continue should be on another flow that scatter-gather is calling. Having it in the same flow as scatter-gather may suppress the error raised but will not continue executing the next component in same flow.
If I have an on-error-propagate set for the scatter-gather and I also have a payload in that. So when the route fails and the handler comes to on-error-propagate, will the payload present there be printed or not.
The statement is a bit confusing to me as it doesn't specify the placement of the on-error-propagate. If a printing component is inside the on-error-propagate scope and the handler comes to on-error-propagate, it will certainly print. However, if all it has is the payload, the flow will never go to the next component and an error object will be returned to the parent flow (or error is thrown if there's no parent flow).

REST vs RPC - *Actual purpose* differences

I started writing web-apps and distributed apps when REST was already popular, so I actually never used RPC.
When searching for a simple explanation of the difference between them, I started to understand, but some examples got me confused.
I saw things like this:
GET /getLastUser
or this:
POST /changeUserName
If REST is meant for resources, and RPC is meant for procedures, isn't it a bad practice using RPC for something like this?
Correct me if I'm wrong, but the way I see it, RPC should be more purely functional.
Meaning that calling a procedure should always:
return the same result for the same arguments
not affect state
So, RPC calls like this:
GET /addTwo?num=5
that return something like this:
{
"result": 7
}
seem more logical to me (although that's a very simple example).
If this question gets closed for being too "opinion-based", I'll just know that I should do whatever the heck I want...
RPC is not meant to be functional. Calling a same procedure twice gives no guarantee about the result.
This question can be answered a few different ways, and pretty deep. I think this might be a fair summary.
With RPC the primitives typically are function names, arguments and results.
With REST the primitive is a 'resource representation'.
So where with RPC you might call a function, in REST you are really sending and retrieving the state of a resource, regardless of protocol.
This means you typically only ask a server 'can you give me the state of this resource', or you tell a server 'here's a new resource state, please store it at this location'. The only successful answers REST will give are "the current state" or "this operation worked", but with RPC the question (function + arguments) and answer (the result) can be anything.
So you can argue that when you describe it like this, RPC is a lot more flexible. It probably is, but because REST confines itself to just transmitting state, you gain a lot of guarantees that a simple RPC-based protocol does not give.
REST is not just about transferring state. The usage hyper-links is another important requirement for a service to be called REST, and this is also something that you don't get 'out of the box' with RPC.
Lastly, it can be argued that HTTP itself is an RPC-like protocol. I think it's possible to build a RESTful service on top of any RPC service.

Backend exception handling for REST app - should we return 4XX error or 200 with error mark

I am working on large-scale web app, and within the project I am developing a REST app for outside clients. I think that this question has not very much to do with the specific technology that I am using, but just in case - it's Django.
We have a convention with the development team that REST resources always return a standard JSON object of type
{'success': <value>,
'object': <value>
'error_msg': <value>,
}
along with the status (200, 201, 403, etc....)
Examples of Django implementation:
return Response({'success': true,
'object': ...,
'error_msg': ...},
status=status.HTTP_200_OK)
The success parameter is assigned true for successful deployment of the resource, and false otherwise.
Now, the entire question here lies in what should be passed in status parameter in those cases when something bad happens - appropriate 4XX code or 200 ?. The development team suggests to ALWAYS use HTTP_200_OK, simply if something bad happened, just assign false to success. The error_msg will contain detailed error message in case of exception.
So the two alternatives among which I can't choose the right one look like this
return Response({'success': false,
'object': ...,
'error_msg': 'Details regarding the error'},
status=status.HTTP_400_BAD_REQUEST)
vs:
return Response({'success': false,
'object': ...,
'error_msg': 'Details regarding the error'},
status=status.HTTP_200_OK)
(in both cases success will equal to false. So in both cases the developer will know that something went wrong by looking at success without having to check status)
However, the very existence of different error codes leaves me with unpleasant doubt that I'm missing something about WHY people have come up with different error codes. And IN WHAT SITUATIONS my project can face trouble if it always returns the same 200 status code.After reading tons of materials, I have no material explanation why specifying appropriate error status codes could outperform the approach of returning 200 status.
HTTP codes are in my opinion a great way to get information on the result of an operation for the following reasons:
They are both machine- and human-readable (at least by developers).
They are integrated in every HTTP transaction, so every library implements mechanisms to deal with them.
The repertoire of error codes is 'standardized' and everyone knows how to deal with it, and it covers a lot of common cases (the DRF framework automatically uses some of those, such as 400, 403 or 405).
By ignoring them, you are increasing the amount of work that you have to implement on your own.
Of course, they might not be enough for particular cases. Suppose you receive a 400 code when you are submitting multiple fields to your API. If you want to know which ones are invalid and why, you still need the value of your error_msg, but the 400 code still simplifies a lot of your logic, since you can filter out a lot of other reasons why the request did not succeed (403, 405...).
Regarding your question:
And IN WHAT SITUATIONS my project can face trouble if it always returns the same 200
Well, if you implement things properly, leaving all error handling to the response date, it should never cause any trouble, but as argued earlier, I feel like this increases the complexity of the task at hand.
Please note that this are just my two cents, and there might be other opinions with better arguments for the opposite case.

Should a wrong parameter passed via REST call throw an error?

I was accessing REST calls, when I passed wrong parameter to GET request it does not throw any http error. Should the design be changed to throw a http error or wrong parameter can be passed to REST call.
Example 1:(parameters are optional)
https://example.com/api/fruits?fruit=apple
Give list of all apple elements
Example 2:
https://example.com/api/fruits?abc=asb
Give list of all fruits
My question is related to example 2, should example 2 throw an error or is it behaving properly?
It's pretty common to ignore parameters that you aren't necessarily expecting. I think example 2 is behaving as it should.
I know that depending on the browser I would sometimes append an extra variable with a timestamp to make sure that the rest call wouldn't be cached. Something like:
https://example.com/api/fruits?ihateie=2342342342
If you're not explicitly doing anything with the extra parameter then I can't see the harm in allowing it.
For a GET request, the request-line is defined as follows
request-line = 'GET' SP request-target SP HTTP-version CRLF
where request-target "...identifies the target resource upon which to apply the request".
That means that the path /api/fruits, the question-mark ? and the query abc=asb are all part of the identifier.
The fact that your implementation happens to use the path to route the request to a handler, and the query to provide arguments, is an accident of your current implementation.
That leaves you with the freedom to decide that
/api/fruits?abc=asb does exist, and its current state is a list of all fruits
/api/fruits?abc=asb does exist, and its current state is an empty list
/api/fruits?abc=asb does exist, and its current state is something else
/api/fruits?abc=asb does not exist, and attempting to access its current state is an error.
My question is related to example 2, should example 2 throw an error or is it behaving properly?
If abc=asb indicates that there is some sort of error in the client, then you should return a 4xx status to indicate that.
Another way of thinking about the parameter handling is in terms of Must Ignore vs Must Understand.
As a practical matter, if I'm a consumer expecting that my filter is going to result in a small result set, and instead I end up drinking a billion unfiltered records out of a fire hose, I'm not going to be happy.
I'd recommend that in the case of a bad input you find a way to fail safely. On the web, that would probably mean a 404, with an HTML representation explaining the problem, enumerating recognized filters, maybe including a web form that helps resend the query, etc. Translate that into your API in whatever way makes sense.
But choosing to treat that as a successful request and return some representation also works, it's still REST, the web is going to web. If doing it that way gives you consumers a better experience, thereby increasing adoption and making your api more successful, then the answer is easy.

Scala actors - worst practices? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
I feel a bit insecure about using actors in Scala. I have read documentation about how to do stuff, but I guess I would also need some DON'T rules in order to feel free to use them.
I think I am afraid that I will use them in a wrong way, and I will not even notice it.
Can you think of something, that, if applied, would result in breaking the benefits that Scala actors bring, or even erroneous results?
Avoid !? wherever possible. You will get a locked system!
Always send a message from an Actor-subsystem thread. If this means creating a transient Actor via the Actor.actor method then so be it:
case ButtonClicked(src) => Actor.actor { controller ! SaveTrade(trdFld.text) }
Add an "any other message" handler to your actor's reactions. Otherwise it is impossible to figure out if you are sending a message to the wrong actor:
case other => log.warning(this + " has received unexpected message " + other
Don't use Actor.actor for your primary actors, sublcass Actor instead. The reason for this is that it is only by subclassing that you can provide a sensible toString method. Again, debugging actors is very difficult if your logs are littered with statements like:
12:03 [INFO] Sending RequestTrades(2009-10-12) to scala.actors.Actor$anonfun$1
Document the actors in your system, explicitly stating what messages they will receive and precisely how they should calculate the response. Using actors results in the conversion of a standard procedure (normally encapsulated within a method) to become logic spread across multiple actor's reactions. It is easy to get lost without good documentation.
Always make sure you can communicate with your actor outside of its react loop to find its state. For example, I always declare a method to be invoked via an MBean which looks like the following code snippet. It can otherwise be very difficult to tell if your actor is running, has shut down, has a large queue of messages etc.
.
def reportState = {
val _this = this
synchronized {
val msg = "%s Received request to report state with %d items in mailbox".format(
_this, mailboxSize)
log.info(msg)
}
Actor.actor { _this ! ReportState }
}
Link your actors together and use trapExit = true - otherwise they can fail silently meaning your program is not doing what you think it is and will probably go out of memory as messages remain in the actor's mailbox.
I think that some other interesting choices around design-decisions to be made using actors have been highlighted here and here
I know this doesn't really answer the question, but you should at least take heart in the fact that message-based concurrency is much less prone to wierd errors than shared-memory-thread-based concurrency.
I presume you have seen the actor guidelines in Programming in Scala, but for the record:
Actors should not block while processing a message. Where you might want to block try to arrange to get a message later instead.
Use react {} rather than receive {} when possible.
Communicate with actors only via messages.
Prefer immutable messages.
Make messages self-contained.