0
votes

When I'm developing, I can connect to cosmodb no problem, but when I deploy it to azure app service, the log stream in app service says that the cosmosdb connection failed. I'm using environment variables so I figured that was the problem espcially since azure didn't copy over the .env file to site/wwwroot so I went to application settings and set the values for each env variable required to connect, but it still fails.

As an experiment, I also tried using a hardcoded connection string to mongodb atlas that works locally, but that failed too when deployed to app service. Maybe it's the port in server.js that's the issue. First time deploying to cloud so I'm a noob. I appreciate any help with this!

020-02-20T23:37:00.887948933Z: [INFO]  2020-02-20T23:37:00: PM2 log:  Use `pm2 show <id|name>` to get more details about an app
2020-02-20T23:37:00.888703339Z: [INFO]  2020-02-20T23:37:00: PM2 log: [--no-daemon] Continue to stream logs
2020-02-20T23:37:00.897860809Z: [INFO]  2020-02-20T23:37:00: PM2 log: [--no-daemon] Exit on target PM2 exit pid=58
2020-02-20T23:37:06.517883906Z: [INFO]  23:37:06 0|server  | BLOB/home/site/wwwroot
2020-02-20T23:37:07.340932229Z: [INFO]  23:37:07 0|server  | (node:69) DeprecationWarning: current URL string parser is deprecated, and will be removed in a future version. To use the new parser, pass option { useNewUrlParser: true } to MongoClient.connect.
2020-02-20T23:37:07.529169475Z: [INFO]  23:37:07 0|server  | (node:69) DeprecationWarning: current Server Discovery and Monitoring engine is deprecated, and will be removed in a future version. To use the new Server Discover and Monitoring engine, pass option { useUnifiedTopology: true } to the MongoClient constructor.
2020-02-20T23:37:07.912008216Z: [INFO]  23:37:07 0|server  | Connection on Failed

enter image description here

server.js

const app = require("./app");
const debug = require("debug")("node-angular");
const http = require("http");
const mongoose = require("mongoose");
var redis = require("redis");

var env = require("dotenv").config();


const normalizePort = val => {
  var port = parseInt(val, 10);

  if (isNaN(port)) {
    e;
    // named pipe
    return val;
  }

  if (port >= 0) {
    // port number
    return port;
  }

  return false;
};

const onError = error => {
  if (error.syscall !== "listen") {
    throw error;
  }
  const bind = typeof port === "string" ? "pipe " + port : "port " + port;
  switch (error.code) {
    case "EACCES":
      console.error(bind + " requires elevated privileges");
      process.exit(1);
      break;
    case "EADDRINUSE":
      console.error(bind + " is already in use");
      process.exit(1);
      break;
    default:
      throw error;
  }
};

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

const onListening = () => {
  const addr = server.address();
  const bind = typeof port === "string" ? "pipe " + port : "port " + port;
  debug("Listening on " + bind);
};

const port = normalizePort(process.env.PORT || "3000");
app.set("port", process.env.PORT || port);

var server = app.listen(app.get("port"), function() {
  debug("Express server listening on port " + server.address().port);
});
1
My guess is something at the network level is blocking the port used by the mongo client in your app since this occurs for Cosmos or Atlas. Maybe check the network settings for your web app for something there.Mark Brown

1 Answers

0
votes

I tried to test my express app to connect my cosmos db mongo api with mongoose.I didn't use PM2 to manage my express app.You could try to test my below code to exclude the issue of network.

Please see my app.js:

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');

var indexRouter = require('./routes/index');
var usersRouter = require('./routes/mongo');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

app.set('port', process.env.PORT || 5000);

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', indexRouter);
app.use('/mongo', usersRouter);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  next(createError(404));
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

app.listen(app.get('port'), function(){
          console.log('Express server listening on port ' + app.get('port'));
          });

mongo.js:

var express = require('express');
var mongoose = require('mongoose');
var router = express.Router();

var url = "mongodb://jaygongmongo:*******[email protected]:10255/?ssl=true&appName=@jaygongmongo@";

/* GET users listing. */
router.get('/', function(req, res, next) {

  new mongoose.connect(url+'/db', {
  useNewUrlParser: true,
  useUnifiedTopology: true
    })
   .then(() => res.send("Connection to CosmosDB successful"))
  .catch(err => res.send(err));
});

module.exports = router;

web.config:

<?xml version="1.0" encoding="utf-8"?>
<!--
     This configuration file is required if iisnode is used to run node processes behind
     IIS or IIS Express.  For more information, visit:

     https://github.com/tjanczuk/iisnode/blob/master/src/samples/configuration/web.config
-->

<configuration>
  <system.webServer>
    <!-- Visit http://blogs.msdn.com/b/windowsazure/archive/2013/11/14/introduction-to-websockets-on-windows-azure-web-sites.aspx for more information on WebSocket support -->
    <webSocket enabled="false" />
    <handlers>
      <!-- Indicates that the server.js file is a node.js site to be handled by the iisnode module -->
      <add name="iisnode" path="app.js" verb="*" modules="iisnode"/>
    </handlers>
    <rewrite>
      <rules>
        <!-- Do not interfere with requests for node-inspector debugging -->
        <rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
          <match url="^app.js\/debug[\/]?" />
        </rule>

        <!-- First we consider whether the incoming URL matches a physical file in the /public folder -->
        <rule name="StaticContent">
          <action type="Rewrite" url="public{REQUEST_URI}"/>
        </rule>

        <!-- All other URLs are mapped to the node.js site entry point -->
        <rule name="DynamicContent">
          <conditions>
            <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True"/>
          </conditions>
          <action type="Rewrite" url="app.js"/>
        </rule>
      </rules>
    </rewrite>

    <!-- 'bin' directory has no special meaning in node.js and apps can be placed in it -->
    <security>
      <requestFiltering>
        <hiddenSegments>
          <remove segment="bin"/>
        </hiddenSegments>
      </requestFiltering>
    </security>

    <!-- Make sure error responses are left untouched -->
    <httpErrors existingResponse="PassThrough" />

    <!--
      You can control how Node is hosted within IIS using the following options:
        * watchedFiles: semi-colon separated list of files that will be watched for changes to restart the server
        * node_env: will be propagated to node as NODE_ENV environment variable
        * debuggingEnabled - controls whether the built-in debugger is enabled

      See https://github.com/tjanczuk/iisnode/blob/master/src/samples/configuration/web.config for a full list of options
    -->
    <iisnode watchedFiles="web.config;*.js"/>
  </system.webServer>
</configuration>

Result:

enter image description here