What could be causing my PUT and DELETE requests to return a 404 status code?

I have encountered a problem with my MEN back-end app. In the express client router, I declared PUT and DELETE requests but they are returning a status 404 not found error. However, the POST request is functioning correctly. Could this be due to a method-override error or something else?

Here is my client.js router:

//Libraries to call
const express = require("express");
const bodyParser = require("body-parser");
const app = express();
const router = express.Router();
const path = require("path");
const mongoose = require("mongoose");
const methodOverride = require("method-override");

//Models to call
const Client = require("../models/client");
const Dossier = require("../models/dossier");

//Create application/x-www-form-urlencoded parser
var urlencodedParser = bodyParser.urlencoded({ extended: true });

//Using method override for CRUD method overloading in HTML form
app.use(express.urlencoded({ extended: true }));
app.use(methodOverride("_method"));

/* _______________________________________CLIENT SECTION________________________________________ */

// Client list interface
router.get("/", async (req, res) => {
  const clients = await Client.find({});
  res.render("clients/index", { clients });
});

// Add a client
router.get("/new", (req, res) => {
  res.render("clients/new");
});

router.post("/", urlencodedParser, async (req, res) => {
  const newClient = new Client(req.body);
  await newClient.save();
  console.log(newClient);
  res.redirect(`/clients/${newClient._id}`);
});

// Specific client interface
router.get("/:id", async (req, res) => {
  const { id } = req.params;
  const client = await Client.findById(id);
  console.log(client);
  res.render("clients/show", { client });
});

// Edit a client
router.get("/:id/edit", async (req, res) => {
  const { id } = req.params;
  const client = await Client.findById(id);
  res.render("clients/edit", { client });
});

router.put("/:id", urlencodedParser, async (req, res) => {
  const { id } = req.params;
  const client = await Client.findByIdAndUpdate(id, req.body, {
    runValidators: true,
    new: true,
  });
  console.log(req.body);
  res.redirect(`/clients/${client._id}`);
});

// Delete a client
router.delete("/:id", async (req, res) => {
  const { id } = req.params;
  const FoldersToDelete = await Dossier.find({ client: id });
  for (let i = 0; i < FoldersToDelete.length; i++) {
    await Dossier.deleteOne(FoldersToDelete[i]);
  }
  const deletedClient = await Client.findByIdAndDelete(id);
  res.redirect("/");
});

// Export the client router
module.exports = router;

And here is my main app index.js where I called the routers and started the server:

//Libraries to call
const express = require("express");
const bodyParser = require("body-parser");
const app = express();
const path = require("path");
const morgan = require("morgan");
const mongoose = require("mongoose");
const methodOverride = require("method-override");

//Routes to add
// For the clients database
const clientRouter = require("./routes/client");
app.use("/clients", clientRouter);
// For the dossiers database
const dossierRouter = require("./routes/dossier");
app.use("/dossiers", dossierRouter);
// For the users database
const userRouter = require("./routes/user");
app.use("/", userRouter);

//Connect to the database
mongoose
 .connect("mongodb://localhost:27017/ProjetDB", {
   useNewUrlParser: true,
   useUnifiedTopology: true,
 })
 .then(() => {
   console.log("MONGO CONNECTION OPEN!!!");
 })
 .catch((err) => {
   console.log("OH NO MONGO CONNECTION ERROR!!!!");
   console.log(err);
 });

//Set dynamic template and PATH
app.set("views", path.join(__dirname, "views"));
app.set("view engine", "ejs");

//Using method override for CRUD method overloading in HTML form
app.use(express.urlencoded({ extended: true }));
app.use(methodOverride("_method"));

//Using morgan middleware to display the status and type of request made
app.use(morgan("dev"));

/*_________________________________ACTIVATE EXPRESS SERVER__________________________________*/

app.listen(5000, () => {
 console.log("APP IS LISTENING ON PORT 5000!");
});

Answer №1

After setting up the routes in the index.js file, I realized that I had forgotten to include the method-override middleware. This mistake caused issues with handling PUT and DELETE requests.

To resolve this issue, we need to reorder the code inside the index.js file as shown below:

//Middleware for overriding HTTP methods in HTML form
app.use(express.urlencoded({ extended: true }));
app.use(methodOverride("_method"));

//Routes to be added
//  for clients database
const clientRouter = require("./routes/client");
app.use("/clients", clientRouter);
//  for dossiers database
const dossierRouter = require("./routes/dossier");
app.use("/dossiers", dossierRouter);
//  for users database
const userRouter = require("./routes/user");
app.use("/", userRouter);

Instead of

//Routes to be added
//  for clients database
const clientRouter = require("./routes/client");
app.use("/clients", clientRouter);
//  for dossiers database
const dossierRouter = require("./routes/dossier");
app.use("/dossiers", dossierRouter);
//  for users database
const userRouter = require("./routes/user");
app.use("/", userRouter);

//Middleware for overriding HTTP methods in HTML form
app.use(express.urlencoded({ extended: true }));
app.use(methodOverride("_method"));

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Setting up a reverse proxy for deploying React applications

I am attempting to implement a setup where multiple containerized SPAs are deployed using a reverse proxy for routing. Each container contains a production build create-react-app served by an express app with the following configuration: app.use(express.s ...

Tips for successfully implementing Angular.js validation within the confines of a <form> element

Having trouble getting my code to work when I place my app inside the <form name="myForm"> tag. Any suggestions on how to make it function properly? (It works when I place myForm inside ng-app, but my app needs to be within the <form> tag) < ...

An effective way to pass a value using a variable in res.setHeader within express.js

Attempting to transmit a file on the frontend while including its name and extension. var fileReadStream = fs.createReadStream(filePath); res.setHeader("Content-disposition", `attachment; filename=${fileName}`); fileReadStream.pipe(res); Encount ...

Enhance tick labels in C3.js with supplementary information

I need a specific format for the tick: tick: { fit: true, multiline: false, outer: false, format: function (x) { var value = this.api.ca ...

Is it possible to incorporate an external javascript file in my CSS file?

Currently, I am attempting to create a setup where my background adjusts based on the width of the user's browser. However, I am constrained by a background specified in the external stylesheet under a specific element. While I have the ability to alt ...

What steps should I take to ensure that this JSON.stringify function functions as intended?

I'm facing a minor challenge in formatting my arrays into the desired JSON structure. Here's the code I've used: var arrData = [{label:Test,value:199.12}, {label:Test2,value:1024}] var data = []; for (var i = 0; i < arrData.length ...

Is there a way to modify page URLs without causing a refresh, regardless of browser?

Despite my extensive searches on various online platforms, including stackoverflow, I have yet to come across a satisfactory answer to my question. While I find the window.history.pushState() and window.history.replaceState() methods quite user-friendly, ...

How can the event listener be utilized with md-autocomplete?

I am currently in the process of developing an angularjs application that incorporates an autocomplete feature. One key aspect of this application is that certain fields cannot be populated until an item has been selected using the autocomplete function. ...

MongoDB: Using the $project operator to filter a sub-array

Let's consider an items (mongoose) schema presented in the simplified format below: { brand: { name: String, }, title: String, description: [{ lang: String, text: String }], shortDescription: [{ lang: String, text: String ...

Harnessing the Power of NextJS Image Component and @svgr/webpack for Seamless Integration

I have recently set up a Next.js site utilizing the @svgr/webpack library. In order to start using an SVG image with the new next/image component, I configured my next.config.js file accordingly. My next.config.js setup looks like this: module.exports = { ...

Leveraging Regular Expressions in express endpoints

Currently in the process of developing a middleware that will execute a specific action (such as generating logs) for every request made to /api/*. I've already written the middleware, however it's failing to work with requests made to /api/me. ...

Is it possible to duplicate a div element and then make changes to both the original and the clone using a single button

I am dealing with an element that has three sub-elements element1, element2, and element3. When I press the button1 command, it filters element1. When I press the button2 command, it filters element2. How can I clone this element and manipulate both th ...

Delete an item from an array based on its index within the props

I am attempting to remove a specific value by its index in the props array that was passed from another component. const updatedData = [...this.props.data].splice([...this.props.data].indexOf(oldData), 1); const {tableData, ...application} = oldData; this ...

Problem with YouTube iFrame API in IE when using JavaScript

Apologies for the unclear heading, but I'm facing a peculiar issue. The YouTube iFrame API works perfectly on all browsers except Internet Explorer. In IE, none of the JavaScript code runs initially. However, when I open DevTools and refresh the page, ...

How can you connect a property to the output of a method in Vue.js when working with TypeScript and vue-property-decorator?

I'm working with a TypeScript single file vue component. I've encountered an issue where the template does not display the values returned by certain component methods. Here's a snippet of the template: <div class="order-items"> ...

Exploring the capabilities of Set() and the for..in loop in JavaScript

function removeDuplicates(menuArray) { let flatmenus = menuArray.flat();//This method combines child and parent arrays into one unique array let combinedMenu = new Set();//Creates an object that removes duplicate elements flatmenus.forEach(dish => ...

Is it possible for me to determine when all images have finished loading in order to update the isLoaded variable to true?

I am using the template below: <template> <div v-if='isLoaded'> <div @click='selectSight(index)' v-for='(sight, index) in sights'> <img :src="'https://maps.googleapis.com/maps ...

What should be placed in the viewRef: MapViewNativeComponentType parameter when utilizing React Native Maps in the current.fitToSuppliedMarkers function?

useEffect(() => { if(!origin || !destination) return; mapRef.current.fitToSuppliedMarkers(["origin", "destination"], { edgePadding: { top: 50, right: 50, bottom: 50, left: 50} }) }, [origin, destination]); I'm currently in t ...

When the progress bar is clicked, the background color changes and then changes back again

https://www.w3schools.com/code/tryit.asp?filename=FG1ZE0NJ4ZX7 https://i.stack.imgur.com/Bnd0k.png I have created a progress bar that resembles the screenshot provided. When I hover over it, the color changes to green. However, I am looking for assistanc ...

Using Javascript, extend the start date by an additional two months in the CRM

My task is to calculate the expiry date by adding two months to a given start date. I came across this code snippet: var startDate = Xrm.Page.getAttribute('new_startdate').getValue(); var expiryDate = new Date(); expiryDate.setMonth ...