Reputation: 1021
I am stuck some silly problem (not sure about this).
I am using Express with Typescript for my API creation.
My problem is as follows:
I have 1 endpoint called Offers, and On that I am doing some operations like findBy Status etc along with CRUD operations, my controller is as follows:
@Get('/findByStatus')
public findByStatus(@QueryParam('status') status: string): Promise<any> {
try {
if (OfferValidator.validateStatus(status)) {
// get data from service
const data = this.offerService.findStatus(status);
if (data) {
return this.offerService.findStatus(status);
} else {
return Promise.reject(new OfferInvalidError(404, 'Offer ID not found'));
}
} else {
return Promise.reject(new OfferInvalidError(404, 'Offer ID not found'));
}
} catch (error) {
return Promise.reject(error);
}
}
@Get('/:id')
@OnUndefined(OfferNotFoundError)
public async one( @Param('id') id: string): Promise<Offer | undefined> {
console.log('called id as well');
try {
if (OfferValidator.lengthValidator(id)) {
return Promise.reject(new OfferInvalidError(400, 'Invalid ID supplied'));
} else {
console.log('coming in validator again');
const data = await this.offerService.findOne(id);
console.log('returned', data);
if (!data) {
return Promise.reject(new OfferInvalidError(404, 'Offer ID not found'));
} else {
data.category = JSON.parse(data.category);
data.tags = JSON.parse(data.tags);
return data;
}
}
} catch (e) {
return Promise.reject(new OfferNotFoundError());
}
}
So now when I call findByStatus with POSTMAN
http://localhost:3000/api/offer/findByStatus?status=sold
then it providing me proper response as well but then it again calling my get by ID method as well, so it showing me errors as follows:
called id as well
coming in validator again
info: [api:middlewares] GET /api/offer/findByStatus?status=available&status=sold 200 61.223 ms - -
returned undefined
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
I have checked with adding console logs and it showing me that when my Find My status function gets executed then get by id function is also executing..
EDIT 1:
I am using Express Typescript Boilerplate for basic setup and for routing.
any idea why its happening ?
Please help me to fix the issue.
Thanks in advance.
Upvotes: 0
Views: 566
Reputation: 4164
This is going to happen due to your routing as you've got two conflicting routes. You've got /findByStatus
and /:id
, both are being triggered because they both technically match the endpoint.
When using /:id
you are saying "pick up anything that goes to the /
with something after it, then give me that value as req.params.id".
My advice would be to drop the /findByStatus
and have it just as /
for several reasons.
Since your /findByStatus
is basically just a type if filter applied to your indexing route you should be able to do something like this.
@Get('/')
public index(@QueryParam('status') status?: string): Promise<any> {
if (status) {
try {
if (OfferValidator.validateStatus(status)) {
// get data from service
const data = this.offerService.findStatus(status);
if (data) {
return this.offerService.findStatus(status);
} else {
return Promise.reject(new OfferInvalidError(404, 'Offer ID not found'));
}
} else {
return Promise.reject(new OfferInvalidError(404, 'Offer ID not found'));
}
} catch (error) {
return Promise.reject(error);
}
}
}
In this scenario, you're now making status
an optional parameter, if it is supplied then you'll filter by the status, if it's not supplied then you could do something else or just return the full dataset.
Not only will this stop your conflicting route issue, but you'll also make your application more RESTful and enable you to extend your filter options against a single route.
Upvotes: 2