I would like to create a REST API with NestJs. But I want to add GraphQL as another top level layer later on. So for the start I have the basic layers controller, service and TypeORM repository. Let's assume you want to update a user's username by id. The controller route could be
PATCH /users/:id/username
Two problems might come up in the service or repository layer:
- The user id might not exist
- The username exists already
The basic flow of this operation would be
- Fetch the user by id
- Handle error if the user does not exist
- Check if the username exists already
- Handle error if the username exists already
- Update the user's username
I'm thinking about how I should handle those errors. I could throw exceptions immediately based on this concept
https://en.wikipedia.org/wiki/Fail-fast
NestJs provides some out of the box exceptions I can use
https://docs.nestjs.com/exception-filters#built-in-http-exceptions
The problem is that I don't think I should throw HTTP exceptions in my service layer. They should be thrown in my controller logic. So what is a common approach for those errors?
- Should I just return
undefined
instead of an updated user? The controller wouldn't know which part failed. - Should I create my own exceptions extending
Error
and throw them? - Due to the fact exceptions come with low performance should the return type of the function be something like
<User | NotFoundError | ConflictError>
?
-
Seems like you are trying to fit your requirements to a design rather than the other way around. Forget about services and ORMs, start with your controller logic and then implement the rest to the contract your controller defines. You might not (probably don't) even need a "service layer." What is it for?Ant P– Ant P2020年02月14日 11:32:05 +00:00Commented Feb 14, 2020 at 11:32
-
The service layer is for the separation of concerns. So the repository should only deal with the database stuff, the service should handle the main logic and the controller should handle the requests/responseshrp8sfH4xQ4– hrp8sfH4xQ42020年02月14日 12:00:32 +00:00Commented Feb 14, 2020 at 12:00
-
so the service layer could be an external project / library toohrp8sfH4xQ4– hrp8sfH4xQ42020年02月14日 12:02:29 +00:00Commented Feb 14, 2020 at 12:02
-
Sounds like you are overengineering your solution and it's causing you problems. You've built an abstraction you don't actually need and now you're fighting against it.Ant P– Ant P2020年02月14日 13:08:47 +00:00Commented Feb 14, 2020 at 13:08
-
so you think I should handle everything in the controller =?hrp8sfH4xQ4– hrp8sfH4xQ42020年02月14日 13:20:14 +00:00Commented Feb 14, 2020 at 13:20
1 Answer 1
You are correct to say you should not throw HTTP specific exceptions in the service layer. The service layer should not have any knowledge of http things.
Most server frameworks have a top level exception handler and an error handling middleware. That top level exception handler could catch any exceptions not handled by your code and return 500 Internal server error.
Usually you can customize that and say okay if it's this language level exception, use this http response. I don't know the framework you are using, as an example in asp.net, when we throw (System.Collections.Generic) KeyNotFoundException then on the top level we return 404. It's not perfect, but it better than directly coupling the two.
Look here: https://docs.nestjs.com/exception-filters
-
thanks for your reply. Would you mind describing the
error handling middleware
a little bit? I thought those run before the incoming request and not after the outgoing response ... right?hrp8sfH4xQ4– hrp8sfH4xQ42020年02月17日 06:52:57 +00:00Commented Feb 17, 2020 at 6:52
Explore related questions
See similar questions with these tags.