'Express subpath GET returns 404 with no content
I'm dealing with an Express + MongoDB (w/Mongoose) project for an interview for which I need to add an endpoint.
The endpoint is a GET /listings/ranking where I'm supposed to get all the products listed and sort them in a descending order by the quantity sold. I wrote the endpoint in the server/api/listing/index.js file (only that endpoint, the other was already there):
var controller = require("./listing.controller");
var config = include("config/environment");
var router = express.Router();
var { route } = require("endpoint-handler")(router)
route.get("/", controller.getAll);
route.get("/:listing_id", controller.getOne);
route.get("/ranking", controller.getMostSold);
module.exports = router;
The code for getMostSold in the controller (server/api/listing/listing.controller):
var Listing = require("./listing.model");
exports.getAll = (req, res) => Listing.find({});
exports.getOne = (req, res) => Listing.findOne({
listing_id: req.params.listing_id
})
.then(listing => {
if (!listing) {
throw { name: "NotFound", statusCode: 404 };
}
return listing;
});
exports.getMostSold = (req, res) => {
var defaultLimit = 3;
Listing.find({})
.sort('-quantity')
.limit(req.query.limit || defaultLimit);
};
And the corresponding spec in server/api/listing/router.spec.js:
var should = require("chai").should();
var request = require('supertest');
var app = include('app').app;
var Listing = require('./listing.model');
describe('Listing', () => {
var samsung = {...};
beforeEach((done) => {
return Listing.create(samsung, done);
});
describe('GET /listings', function() {
it('should return all the listings', (done) => {
request(app).get('/listings').expect(200, [samsung], done);
});
});
describe('GET /listings/:listing_id', function() {
it('should return the requested listing', (done) => {
request(app).get('/listings/MLA1111').expect(200, samsung, done);
});
it('should return 404 Not Found when the requested listing does not exist', (done) => {
request(app).get('/listings/WRONGID').expect(404, done);
});
});
describe('GET /listings/ranking', function() {
var motoG = {...};
var onePlus = {...};
var iPhone = {...};
Listing.create(motoG);
Listing.create(onePlus);
Listing.create(iPhone);
it('should return the top 3 most sold listings since monitoring started', (done) => {
request(app).get('/listings/ranking').expect(200, [samsung, motoG, onePlus, iPhone], done);
});
it('should return the top N most sold listings since monitoring started', (done) => {
var topN = 2;
request(app).get(`/listings/ranking?limit=${topN}`).expect(200, [motoG, samsung], done);
});
});
Both specs for my endpoint are failing while the other works just fine. And it's not that they're returning something else, they're just not returning anything at all other than an empty 404. I tried changed my endpoint's controller's code to be just Listing.find({}) like for the .getAll method, but it's still returning {}.
I suspect it's just a routing problem because of what I just said. Even though I changed the code, it's like it's not recognizing that there's an endpoint called /listings/ranking.
Here's the server/routes.js file just in case:
var errors = require("./components/errors");
module.exports = (app) => {
app.use("/listings", require("./api/listing"));
app.route("/:url(api|components|app|bower_components|assets)/*").get(errors[404]);
};
Solution 1:[1]
DISCLAIMER: First of all, the way I posted the question was without all of the code in all of the files because I thought it would clutter the post with endpoints and tests that weren't affecting mine. Now the question has another endpoint which is what was causing trouble: GET /listings/:listing_id.
Apparently in Express the order of the endpoint definition matters so what happened was that my test was trying to interpret GET /listings/ranking as if ranking was a listing_id only because the /:listing_id was defined before it. So it was returning 404 because no listing with the ID "ranking" existed.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Lucas S. G. |

