Приложение для разрыва кода соединения базы данных Mongodb - PullRequest
1 голос
/ 21 февраля 2020

Во время разработки я использовал этот блок кода mongodb для подключения к базе данных, и он работал безупречно, но не при развертывании на Azure.

mongoose
  .connect(
    "mongodb://" +
      process.env.COSMOSDB_HOST +
      ":" +
      process.env.COSMOSDB_PORT +
      "/" +
      process.env.COSMOSDB_DBNAME +
      "?ssl=true&replicaSet=globaldb",
    {
      auth: {
        user: process.env.COSMOSDB_USER,
        password: process.env.COSMOSDB_PASSWORD
      }
    }
  )
  .then(() => console.log("Connection to CosmosDB successful"))
  .catch(err => console.error(err));

У меня были проблемы с его получением подключиться при развертывании моего приложения к azure, поэтому мне был предоставлен другой блок кода mongodb для использования из azure support

var mongoDBurl = process.env.MONGODB_CONNECTION;
mongoose.connect(mongoDBurl, { useNewUrlParser: true });

var db = mongoose.connection;

db.on('error', console.error.bind(console, 'MongoDB connection error:'));

db.once('open', (callback) => {
    console.log('MongoDB connectted!!');
});


, но когда я использую этот код mongodb вместо исходного, тогда я получаю Cannot set headers after they are sent to the client при попытке войти в мое приложение. Почему это так?

логин api

router.post("/login", (req, res, next) => {
  let fetchedUser;
  let username;
  User.findOne({ email: req.body.email })
    .then(user => {
      if (!user) {
        return res.status(401).json({
          message: "Auth failed"
        });
      }

      fetchedUser = user;
      username= user.username;
      return bcrypt.compare(req.body.password, user.password);
    })
    .then(result => {
      if (!result) {
        return res.status(401).json({
          message: "Auth failed"
        });
      }
      const token = jwt.sign(
        {
          email: fetchedUser.email,
          userId: fetchedUser._id,
          username: username
        },
        "secret_this_should_be_longer",
        { expiresIn: "1h" }
      );

      res.status(200).json({
        token: token,
        expiresIn: 3600,
        userId: fetchedUser._id,
        username: username
      });
    })
    .catch(err => {
      return res.status(401).json({
        message: "Auth failed"
      });
    });
});

1 Ответ

3 голосов
/ 21 февраля 2020

Причина

Это потому, что оператор return в вашем обещании не заканчивает вашу очередь then. Вы отвечаете 401, если вы не нашли User, а на втором then вы отвечаете 401 снова, если нет результата.

Express говорит вам, что вы можете отправлять заголовки дважды, что правда. Я думаю, что в вашем коде нет ничего, связанного с MongoDB.

Совет: попробуйте преобразовать ваш маршрут в try/catch/await код, чтобы лучше понять происходящее

Возможное решение

Изменить: это должно работать

// You don't need next as you're ending the request here and not calling it anyway
router.post("/login", async (req, res) => {
  const user = await User.findOne({ email: req.body.email });

  if (!user) {
    return res.status(401).json({
      message: "Auth failed"
    });
  }

  const { username } = user;

  const goodPassword = bcrypt.compareSync(req.body.password, user.password);

  if (!goodPassword) {
    return res.status(401).json({
      message: "Auth failed"
    });
  }

  const token = jwt.sign( // Double check if this call is synchronous or not (needs await or not)
    {
      email: user.email,
      userId: user._id,
      username: username
    },
    "secret_this_should_be_longer",
    { expiresIn: "1h" }
  );

  // Maybe store the token in the cookies instead of sending back, as you wish !

  res.status(200).json({
    token: token,
    expiresIn: 3600,
    userId: user._id,
    username: username
  });
});

Обратите внимание, что использование await помогает вам понять ваш код!

Аутентификация MongoDB

Относительно ваша аутентификация MongoDB, вам нужно использовать те же учетные данные, что и в первом методе

const { COSMOSDB_HOST, COSMOSDB_PORT, COSMOSDB_DBNAME, COSMOSDB_USER, COSMOSDB_PASSWORD } = process.env;

mongoose.connect(`mongodb://${COSMOSDB_HOST}:${COSMOSDB_PORT}/${COSMOSDB_DBNAME}?ssl=true&replicaSet=globaldb`,
  {
    auth: {
      user: COSMOSDB_USER,
      password: COSMOSDB_PASSWORD,
    },
  },
);

const db = mongoose.connection;

db.on('error', console.error.bind(console, 'MongoDB connection error:'));

db.once('open', (callback) => {
    console.log('MongoDB connected!!');
});

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...