Reputation: 6970
I have a nestjs application in which I created a pipe to check if the value is a valid URL. If the URL is invalid, throw an error. This is used in a controller to save an item into the database.
I just realized the pipe would throw 500 with Internal Server Error, I had to check the server log to see if it's actually from the pipe.
I wonder if there's a way that we can have an HTTP response directly with the message?
The pipe code I have is...
import { BadRequestException, Injectable, PipeTransform } from '@nestjs/common';
@Injectable()
export class ValidUrlPipe implements PipeTransform {
transform(website: string) {
if (website === '') return website;
const validProtocols = ['http:', 'https:'];
const { protocol } = new URL(website);
if (validProtocols.includes(protocol)) {
return website;
}
throw new BadRequestException(`invalid website value: ${website}`);
}
}
the controller using the pipe looks like
@Post()
create(
@Body('website', ValidUrlPipe) website: string,
@Body() createTvDto: CreateTvDto,
@CurrentUser() user: User,
) {
return this.televisionsService.create(user._id, createTvDto);
}
Thank you so much in advance for any suggestions/solutions.
EDIT: I added an image of the error thrown by using Postman to call the endpoint
Upvotes: 1
Views: 605
Reputation: 847
Dora, let me help you with the actual solution:
import { BadRequestException, Injectable, PipeTransform } from '@nestjs/common';
@Injectable()
export class ValidUrlPipe implements PipeTransform {
transform(website: string) {
if (website === '') return website;
const validProtocols = ['http:', 'https:'];
try {
const { protocol } = new URL(website);
if (validProtocols.includes(protocol)) {
return website;
}
} catch (error) {
// Maybe add another bit of logging here for your own records if it is of interest?
throw new BadRequestException(`invalid website value: ${website}`);
}
}
}
For those of you privileged with Node 20:
Instead of wrapping it all in a try/catch, you could use the static method URL.canParse().
Implemented for your pipe:
import { BadRequestException, Injectable, PipeTransform } from '@nestjs/common';
@Injectable()
export class ValidUrlPipe implements PipeTransform {
transform(website: string) {
if (website === '') return website;
const validProtocols = ['http:', 'https:'];
if (URL.canParse(website)) {
// URL.canParse(...) returns a boolean if the url is valid or not
const { protocol } = new URL(website);
if (validProtocols.includes(protocol)) {
return website;
}
}
throw new BadRequestException(`invalid website value: ${website}`);
}
}
Upvotes: 0
Reputation: 557
this line const { protocol } = new URL(website);
will throw an error if the website
parameter is not a valid URL. you could put validation to check if the parameter is a valid URL. it's better to have a try/ catch block to catch errors and return proper exceptions.
Upvotes: 0
Reputation: 70131
Your issue is that the new URL()
call is throwing an exception. You can wrap that in a try/catch
block to transform it to the proper BadRequestException
you are wanting to throw. Otherwise, I'd probably just use a simple regex /https?:\/\//.test(website)
to validate that the passed website is indeed an HTTP or HTTPS website.
Upvotes: 0