1

Here is my server.js:

  import express from "express";
import mongoose from "mongoose";
import productRouter from "./routers/productRouter.js";
import dotenv from "dotenv";

dotenv.config();

const app = express();
app.use(express.json());
let prof = process.env.PROF;

mongoose.connect(
 `${prof}`
);

// Add headers before the routes are defined
app.use(function (req, res, next) {
  // Website you wish to allow to connect
  res.setHeader("Access-Control-Allow-Origin", "*");

  // Request methods you wish to allow
  res.setHeader(
    "Access-Control-Allow-Methods",
    "GET, POST, OPTIONS, PUT, PATCH, DELETE"
  );

  res.header("Access-Control-Allow-Headers", "Content-Type");
  // Request headers you wish to allow
  // res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');

  // Set to true if you need the website to include cookies in the requests sent
  // to the API (e.g. in case you use sessions)
  res.setHeader("Access-Control-Allow-Credentials", true);

  // Pass to next layer of middleware
  next();
});
/*
app.get("/api/products", (req, res) => {
  res.send(data);
});*/

app.use("/api/products", productRouter);

app.get("/", (req, res) => {
  res.send("Server is ready");
});

const port = process.env.PORT || 5000;
app.listen(port);

Going inside productRouter.js ...

  import express from "express";
import mongoose from "mongoose";
import data from "../data.js";
import Product from "../models/productModel.js";
import { payment } from "./paymentController.js";

const productRouter = express.Router();

productRouter.use("/pay", async (req, res, next) => {
  // dont store cart in db, store it in local storage. On checkout get Id of all items in cart. Then find their prices from the db and charge correctly.
  console.log("middleware ran");
  console.log(req.body);
  const productIdsAndAmounts = req.body.basketItems.items.map((item) => {
    return { id: item.id, amount: item.amount };
  });

  // this works faster (apparently)
  /*
  const objIds = productIds.map((id) => mongoose.Types.ObjectId(id));
  const orderedItems = await Product.find({
    _id: { $in: objIds },
  });
*/
  // this sends more query requests to db
  const orderedItems = await Promise.all(
    productIdsAndAmounts.map((productId) => {
      return Product.findById(productId.id);
    })
  );

  let i = -1;
  let productIdsPricesAmounts = [];
  orderedItems.forEach((item) => {
    i = i + 1;
    productIdsPricesAmounts.push({
      id: item.id,
      price: item.price,
      amount: productIdsAndAmounts[i].amount,
    });
  });
  console.log(productIdsPricesAmounts);

  const prices = productIdsPricesAmounts.map((item) => {
    return item.price * item.amount;
  });
  const reducer = (prevValue, currValue) => prevValue + currValue;
  const totalTotalPrice = prices.reduce(reducer);

  console.log(totalTotalPrice);

  req.totalPrice = totalTotalPrice;

  //console.log(orderedItems);
  //console.log(productIdsAndAmounts);

  // console.log(req.body.user); // adres
  next();
});

productRouter.get("/", async (req, res) => {
  const products = await Product.find({});
  res.send(products);
});

productRouter.post("/pay", payment);

export default productRouter;

Now to the paymentController.js:

export const paymentController = async (req, res, next) => { 
console.log(req.body.basketItems)
/* returns contents of the body like expected, i can do whatever i want with it*/ 
}

The behaviour, i can get is: Client sends request to "api/products/pay", i have access to req.body in paymentController.

The behaviour, i want is: Client sends request to "api/products/pay", the request first goes through a middleware where i do some calculations on it, then i forward the new variable to my paymentController. The problem is req.body is {} in middleware productRouter.use(), but available in paymentController

What am I doing wrong ? I'm new to express and i don't exactly know what I'm doing yes. I want to have access to req.body inside productRouter. I'm guessing i set up the middleware wrong or something like that. But I can't see what i did wrong.

Koray Aydemir
  • 310
  • 3
  • 9
  • 1
    You are definitely right. I'm editing and doing my best to fix it now. Also the question itself was a bit wrong, i changed it too (req.body returns empty object inside middleware, not undefined like i said before the edit) – Koray Aydemir Oct 29 '21 at 00:59
  • My guess is that your _"CORS STUFF"_ part isn't handling pre-flight requests correctly and your middleware is trying to handle the `OPTIONS` request. Instead of rolling your own CORS middleware, I recommend you just use the [cors package](https://www.npmjs.com/package/cors) which is mature and well tested – Phil Oct 29 '21 at 01:03
  • Please post your actual code. Are you sure that your middleware calls `next()` only after you've done the payment request? It sounds like you might be asynchronously accessing a request that has already been torn down. – Bergi Oct 29 '21 at 01:06
  • I think yes, also i re-edited the question to include my whole code. Should've done that from the start but. – Koray Aydemir Oct 29 '21 at 01:13
  • As expected, your CORS implementation is incomplete. [Here's an example of how it should be done](https://github.com/expressjs/cors/blob/master/lib/index.js#L163) (or you can just use that package as suggested earlier) – Phil Oct 29 '21 at 01:19
  • Wow, yes it was that simple thanks a lot, it works as expected now. I just downloaded the cors package instead of having a huge incomplete cors code there. – Koray Aydemir Oct 29 '21 at 01:34

2 Answers2

0

Can You Use Router For Example :

user.ts

import express from "express";
let UserRoute = express.Router()
UserRoute.get('/',function (req,res) {
    res.json('Hello World')
})

export { UserRoute }

App.ts

import express from "express";
import cors from "cors";
import {  UserRoute } from "./routes/v1/user"
const http = require('http');
const app = express();
const server = http.createServer(app);
const  PORT : string|number = process.env.PORT || 5000;
app.use(cors());
app.use(express.json());
app.use('/',UserRoute)



//Run Server And Listen To Port
server.listen(PORT,()=>{
    console.log("Server UP")
})
Kareem Adel
  • 371
  • 2
  • 10
0

Guess this is your main route where you want to add middleware function right Create a middle were function with name "abc" export from there as name "abc"

Now, here in main route you can use that function as a middleware

productRouter.post("/pay",abc, payment);

here abc is your middleware function

Smit Gajera
  • 1,001
  • 1
  • 8
  • 26