无法使用Sequelize从本地Node应用程序连接到Heroku的PostgreSQL数据库

24

我正在尝试使用Sequelize从本地的nodejs应用程序连接到Heroku postgresql数据库。我按照这两个指南进行操作,在heroku服务器端一切都运行得非常完美,但是当我在我的Mac本地运行它时,我的节点应用程序无法连接到Heroku。

以下是我启动本地应用程序的方式:

DATABASE_URL=$(heroku config:get DATABASE_URL) nodemon

我理解:

Sequelize: Unable to connect to the database:

但是我通过这样做获取了正确的URL:

echo $(heroku config:get DATABASE_URL)

这些命令都可以正常运行:

heroku pg:psql
psql $(heroku config:get DATABASE_URL)

这是我的Node.js代码:

var match = process.env.DATABASE_URL.match(/postgres:\/\/([^:]+):([^@]+)@([^:]+):(\d+)\/(.+)/)
sequelize = new Sequelize(match[5], match[1], match[2], {
    dialect:  'postgres',
    protocol: 'postgres',
    port:     match[4],
    host:     match[3],
    logging: false
})

sequelize
.authenticate()
.complete(function(err) {
    if (!!err) {
        log('Sequelize: Unable to connect to the database:', err);
    } else {
        http.listen(process.env.PORT || config.server.port, function(){
            log('Web server listening on port '+process.env.PORT || config.server.port);
        });
    }
});

我尝试将 native: true 添加到 sequelize 选项中,但是我遇到了以下问题:

    /Users/clement/Projets/XMM/node_modules/sequelize/lib/sequelize.js:188
      throw new Error('The dialect ' + this.getDialect() + ' is not supported.
            ^
Error: The dialect postgres is not supported. (Error: Please install postgres package manually)
    at new module.exports.Sequelize (/Users/clement/Projets/XMM/node_modules/sequelize/lib/sequelize.js:188:13)
    at Object.<anonymous> (/Users/clement/Projets/XMM/server.js:17:14)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)
    at startup (node.js:119:16)
    at node.js:929:3

即使做了:

npm install pg
npm install -g pg
brew install postgresql

顺便说一下,这是有效的:

var pg = require('pg');
pg.connect(process.env.DATABASE_URL+'?ssl=true', function(err, client, done) {
    if (err) return console.log(err);
    client.query('SELECT * FROM pg_catalog.pg_tables', function(err, result) {
        done();
        if(err) return console.error(err);
        console.log(result.rows);
    });
});

但我宁愿使用Sequelize。


现在他们在 https://devcenter.heroku.com/articles/heroku-postgresql#connecting-in-node-js 上提供了一些官方的 Node.js 文档,虽然不是针对 Sequelize 的,但可能也会引起兴趣。 - Ciro Santilli OurBigBook.com
5个回答

63

好的,通过浏览Sequelize源代码找到了答案: https://github.com/sequelize/sequelize/blob/master/lib/dialects/postgres/connection-manager.js#L39

要为PG连接激活SSL,您不需要使用native: truessl: true,而是需要使用dialectOptions.ssl: true,因此以下内容最终有效:

sequelize = new Sequelize(process.env.DATABASE_URL, {
    dialect: 'postgres',
    protocol: 'postgres',
    dialectOptions: {
        ssl: true
    }
});

为了解决在 SequelizeConnectionError: self signed certificate 中提到的 node-postgres 版本 8 上的 self signed certificate bug,您可以使用以下方法:

sequelize = new Sequelize(process.env.DATABASE_URL, {
    dialect: 'postgres',
    protocol: 'postgres',
    dialectOptions: {
        ssl: {
            require: true,
            rejectUnauthorized: false
        }
    }
});

1
谢谢!我花了很长时间才弄清楚。其他在线指南有误(我也试图使用本地语言)。需要注意的是,sequelize的错误信息不太好(实际错误不在顶部),所以如果你收到一个方言不支持的消息,请往下看一点...在我的情况下,缺少pg-hstore并且需要安装它。 - phillipwei
谢谢您。也许这是一个超级新手问题 - 我已经在服务器上将ssl选项设置为true,并在客户端上添加了此选项。连接正在工作。就这样吗?我需要做其他任何事情来启用SSL吗?非常感谢。 - Chris Houghton
嗨,Chris,我无法回答你的问题,而且它与我们讨论的主题没有直接关系,所以我认为你应该在stackoverflow上创建一个全新的问题以获取帮助。 - clemlatz
天哪,我花了3个小时解决这个错误。非常感谢! - spectre10
5
为了解决“self signed certificate”错误,请参考此帖子:https://dev59.com/6VMH5IYBdhLWcg3wnASa - Noah
显示剩余2条评论

17

您不再需要解析DATABASE_URL环境变量,Sequelize构造函数可以接受连接URL:

sequelize = new Sequelize(process.env.DATABASE_URL, {
    dialect: 'postgres',
    protocol: 'postgres',
    dialectOptions: {
        ssl: true
    }
});


4
你已经回答了自己的问题(dialectOptions.ssl: true),我只是在此基础上提供了一个更简单的解决方案。 - Giovanni P.

11

需要在ssl下添加dialectOptions选项

 "development": {
    "username": process.env.DB_USERNAME,
    "password": process.env.DB_PASSWORD,
    "database": process.env.DB_NAME,
    "host": process.env.DB_HOST,
    "dialect": process.env.DB_DIALECT,
    "dialectOptions": {
        ssl: {
            require: true,
            rejectUnauthorized: false
        }
    }
},

数据来源为官方Sequelize Github。


1
这对我有效,而被接受的答案则没有。可能是最近更新的原因。 - atultw
rejectUnauthorized: false,在 https://dev59.com/6VMH5IYBdhLWcg3wnASa 也有提及。目前 Heroku 定义的唯一 env 变量似乎是 process.env.DATABASE_URL,但 Sequelize 通过 https://dev59.com/Z14c5IYBdhLWcg3wqLte#27688357 可以正确解析其中的所有字段。 - Ciro Santilli OurBigBook.com

2

你只需要这两个步骤

  1. 在你的 POSTGRES 数据库 URI 后面添加 ?sslmode=require
  2. 确保在你的 dialectOptions 中有 rejectUnauthorized: false
const sequelize = new Sequelize(`${process.env.DATABASE_URI}?sslmode=require`, {
  url: process.env.DATABASE_URI,
  dialect: 'postgres',
  logging: false,
  dialectOptions: {
    ssl: {
      require: true,
      rejectUnauthorized: false, // very important
    }
  }
}

如需更多信息,请参阅Heroku DevCenter上的文章
https://devcenter.heroku.com/articles/heroku-postgresql#heroku-postgres-ssl


1

我也遇到了同样的问题,对于这种情况,您可以考虑参考以下文档示例,了解如何连接Heroku数据库:

https://sequelize.readthedocs.io/en/1.7.0/articles/heroku/

最后,我实现了一个类似以下代码的代码:

const sequelize = new Sequelize(
    process.env.DATABASE_NAME_DB_CONFIG,
    process.env.USER_NAME_DB_CONFIG,
    process.env.USER_PASSWORD_DB_CONFIG,
    {
        host: process.env.HOST_DB_CONFIG,
        dialect: process.env.DIALECT_DB_CONFIG,
        protocol: process.env.PROTOCOL_DB_CONFIG,
        logging:  true,
        dialectOptions: {
            ssl: true
        },
        pool: {
            max: 5,
            min: 0,
            idle: 10000
        }
    }
);

在编程中,如果需要考虑方言选项ssl: true,则需要注意这一点。

这就是你需要知道的全部内容。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接