14

I'm writing a RESTful API in Nest, which I recently started using and love so far. However, I'm struggling with finding a clean pattern to handle 204 No Content responses for my GET routes. Any recommendations?

I'm a little surprised there isn't something built into the framework for returning 204 if the object returned by a GET controller method is empty -- if there is, I haven't found it yet. If there truly isn't, I'm also wondering if this is worth a feature request on GitHub.

I've tried the following:

  • Exposing the Express res property using @Response() as a Controller method parameter, then using res.sendStatus(204) if the response is empty. However, this requires me to manually send 200 responses too, whereas I'd like to still rely on the framework to handle the request-response cycle and keep my controller methods as clean as possible.
  • Looked into using an interceptor for checking if the response object is empty, then writing the 204 status code into the response there. I don't really want to do this because the status code could change later due to an exception filter.
  • Using middleware to write the response code, but my middleware executes before it gets routed to the controller and I need to check if the response is empty after that. res.on('send') didn't seem to intercept the response on its way out, either.
  • Throwing a custom NoContentException for my exception filter to handle. Although it's odd to throw an exception for a successful response code, I think this is the way I'll proceed in the meantime since my exception filter is the last thing that will execute in the code I've written.
Kim Kern
  • 54,283
  • 17
  • 197
  • 195
Eric
  • 141
  • 1
  • 1
  • 3
  • see the update in my answer, it is now possible with Interceptors. :-) – Kim Kern May 06 '20 at 08:14
  • The more our team uses frameworks, the more we are convinced decorators are a poor choice for many things in general... – myol Jun 07 '22 at 09:30

4 Answers4

16

Looking at this example:

@Post()
@HttpCode(204)
create() {
  return 'This action adds a new cat';
}

This is all you need to do. It return's 204 for you.

Amiga500
  • 5,874
  • 10
  • 64
  • 117
5

Update v6.1.0

Since v6.1.0 it is possible to set the response code in an Interceptor, see this PR.


Outdated answer

Unfortunately, this does not seem to be possible yet. In the docs it says:

Often, your status code isn't static but depends on various factors. In that case, you can use a library-specific response (inject using @Res()) object (or, in case of an error, throw an exception).

You also cannot just set the response code in an Interceptor without sending it (instead of sendStatus) because, as Kamil said in this thread:

global response controller's logic is the last step performed just before sending a final result through the network (that's the place where default status codes come in).

So if you (understandably) don't want to use @Res in every controller, an ExceptionFilter seems to be the best option, although it does not feel perfectly right.

Since other people seem to have the exact same problem, a feature request might be a good idea. :-)

Kim Kern
  • 54,283
  • 17
  • 197
  • 195
  • 1
    I found these answers (also from @kim-kern) useful as well when I ran into this situation: https://stackoverflow.com/questions/55406194/nestjs-set-httpstatus-in-interceptor https://stackoverflow.com/questions/51695868/how-to-return-a-404-http-status-code-when-promise-resolve-to-undefined-in-nest – John Henderson Nov 20 '20 at 19:36
2

Using the @HttpCode(204) decorator wasn't helpful for my situation because I didn't want a 204 to throw when the query returned an array of data. I want it to throw a 204 when the array is empty even though the query was successful.

That said, since I'm building a simple MVP, I opted to throw HttpStatus.NO_CONTENT; which is good enough for the time being.

Open to cleaner ways (best practice) of achieving the same result.

0
  • Initially for the practice of 204 No Content response producing, it has been mentioned in official document at the position of introducing nestjs status code annotation feature.
  • About the thought of generating 204 response by checking whether the response content is empty

    it could be possible and practicable in Express.js programming directly or building up an interceptor as a middleware plugin into nestjs framework usage, as mentioned in @kim-kern answer.

    At the api design level however, it is not a required feature because one api should be ideally designed as one success response, which means only one success code would be available for one endpoint. From this view, the status code annotation could be acceptable.

千木郷
  • 1,595
  • 2
  • 19
  • 30