Files exception filter
An exception filter for common file-related errors.
An interesting feature we could implement is an exception filter for files. However, it is important to understand that it will only catch errors related to file validation. In case an error of type ENOENT occurs (file or directory not found), it won't be handled. This is because this kind of error is related to problems in the code. So, if this happens, we should fix these bugs instead of throwing an exception. In some cases it may make sense to handle it, like in the downloadImage()
method, as a filename
for a non-existing file
may be sent and thus, this problem is not code-related anymore.
This may remind of the discussion Checked/Unchecked exceptions, common in Java.
The idea is to make the file validation throw a specific type of exception in case of failure, so that this exception may be catched by the filter. Just for this purpose, we'll use the UNPROCESSABLE_ENTITY status. Once in the filter, a more adequate status
will be used for the concrete case. What we'll do then, is to go back to the file-validation.util file and add a new function, responsible for creating a ParseFilePipe
with the validators
we defined previously and also the mentioned status
.
We may then simplify the second parameter of createFileValidators()
by removing the rest parameter, as this function is not called directly anymore.
This way, back in the ProductsController
, in uploadImages()
, we even get a simpler result.
You may be thinking: doesn't this increase the code coupling? As if a more specific configuration is desired for the ParseFilePipe
, this function may not be employed. This is a valid thought. It depends on how this code is intended to be used. If it's assumed that, practically everywhere files are managed, this pattern will be used, then it may be alright. If more flexibility is needed, then another approach can be worked upon. And this may change during the project itself. In the end, it depends on the specific details of the business logic, and both the pros and cons of each possible approach should be considered.
Commit - Unprocessable entity as default exception for file validation
Now, let's create the exception filter. Also enable it globally in the FilesModule
.
Inside it, let's make it catch the previously defined exception.
In the catch()
method, obtain the response
and extract the message
from the exception
.
When dealing with file-related errors, we have two more possibilities of HTTP status. Let's then return to http-error.util in order to add them.
Now, as we have already done before, let's create some constants to aid us.
There's no description for the max size as it is already descriptive enough.
Then, add new regexes for these situations.
The next step is to create methods for extracting the maxSize
and fileTypes
from the message. The maxSize
is a number after "less than", and the fileTypes
can be found between slashes, separated by pipes. Therefore, each method will have its own logic to extract the data.
As the maxSize
is in bytes, the bytes library will be used again. However, this time the opposite process will occur: it will transform the value in bytes into a readable string.
Remember to import the bytes library correctly, adding * as
.
The fileTypes
have backslashes that should be removed for the next step. In the message
, now the media types can be found, due to our previous fix. This time, we'll also perform the opposite process and obtain their respective extensions, using the extension()
function from mime-types.
As the last step, let's create the method createErrorData()
. It will return fields which some of them may or may not be generated depending on the error message
.
If the message
doesn't match any snippet, the BAD_REQUEST status is maintained alongside the original message
. This is useful, for example, when no files are sent.
The expectedFileTypes
has a union type because the extension()
function returns false if it cannot identify the extension.
The only remaining step now is to, in the catch()
method, extract the data and compose the response
.
With this, we have finished the files exception filter.
Commit - Creating the files exception filter
Last updated