Home > Enterprise >  Express subpath GET returns 404 with no content
Express subpath GET returns 404 with no content

Time:03-17

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]);
};

And here's what the project structure looks like: Project structure

CodePudding user response:

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.

  • Related