why GET method does not work while POST works for same api calll in express?

Issue

I got confused while running my code.
I am trying to make an API route for searching books and when I apply POST method it works and does what I want to achieve while there is nothing in body but when I apply GET method it shows following error:

CastError: Cast to ObjectId failed for value "search" (type string) at path "_id" for model "bookmodel"
    at model.Query.exec (E:\FullStacks\BookStore\node_modules\mongoose\lib\query.js:4803:21)
    at model.Query.Query.then (E:\FullStacks\BookStore\node_modules\mongoose\lib\query.js:4902:15)
    at processTicksAndRejections (node:internal/process/task_queues:96:5) {
  messageFormat: undefined,
  stringValue: '"search"',
  kind: 'ObjectId',
  value: 'search',
  path: '_id',
  reason: BSONTypeError: Argument passed in must be a string of 12 bytes or a string of 24 hex characters or an integer

what could be the reason behind it?
route:

router.get("/search", bookcontoller.searchBook)
async searchBook(req, res) {
    try {
      const { query } = req.query;
      console.log(query);
      if (!query) {
        return res.status(400).json({ success: false, msg: "query not found" });
      }

      const searchResult = await bookModel.find({$or:[{name:{$regex:".*"+query+".*"}}, {genre:{$regex:".*"+query+".*"}}]})
      if(searchResult.length == 0){
        return res.json({success:false, msg:"nothing found of that query"})
      }
      return res.status(200).json({success:true, msg:"search has been successful", searchResult})

    } catch (error) {
      return res.status(400).json(error);
    }
  }

url:

localhost:8000/book/search?query=hi

Solution

You very likely also have a route looking like this:

router.get('/:id', ...)

And the handler of that route uses req.params.id to perform a query on bookModel to find the book with that id.

Then, you declared the route you’re showing:

router.get('/search', …)

Express does not pick the best route handler that matches, but the first. And a request for /search will match the route for /:id just fine. So you’re performing a query against bookModel using the word "search" (now in req.params.id) as _id, which fails because that’s not a valid ObjectId.

The solution is to always declare more specific route handlers first:

router.get('/search', …)
router.get('/:id', …)

Answered By – robertklep

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published