问题描述
所以我想做一个包含数据库、后端和移动前端的小项目。我在树莓派上有一个 mariadb 数据库,并且为来自任何地方的连接设置了一切。我使用 TypeORM 创建了我的后端服务器并将其托管在 heroku 上。问题是我的 heroku 服务器有一个动态 IP,我只想拥有少量列入白名单的 IP。所以我将 quotaguard 添加到我的 heroku 应用程序中。问题是设置代理连接(来自 quotaguard documentation)的唯一方法是通过创建 SockConnection
对象的socksjs(再次来自quotaguard 的文档)。我知道如果我使用 mysql.createConnection()
有一个 stream
选项允许我传入该对象,但我没有在 TypeORM 的 createConnection
函数中看到它。我有一个名为 sockConn
的变量,我已经验证了在 quotaguard 仪表板上建立了连接,但我不知道如何将它添加为 TypeORM createConnection
函数的选项。
这是我项目中的 index.ts 文件:
import "reflect-metadata";
import {createConnection,getConnectionManager} from "typeorm";
import express from "express";
import {Request,Response} from "express";
import {Routes} from "./routes";
import { DB_CONNECTION } from "./database";
import { MysqlConnectionOptions } from "typeorm/driver/mysql/MysqlConnectionOptions";
import { config } from 'dotenv';
import { parse } from 'url';
var SocksConnection = require('socksjs');
config().parsed
const setupConnection = () => {
DB_CONNECTION.username = process.env.DB_USER;
DB_CONNECTION.password = process.env.DB_PASS;
DB_CONNECTION.host = process.env.DB_HOST;
DB_CONNECTION.port = parseInt(process.env.DB_PORT);
DB_CONNECTION.debug = true;
// ---- this section from quotaguard documentation ---- //
var proxy = parse(process.env.QUOTAGUARDSTATIC_URL),auth = proxy.auth,username = auth.split(':')[0],pass = auth.split(':')[1];
var sock_options = {
host: proxy.hostname,port: 1080,user: username,pass: pass
};
var sockConn = new SocksConnection({host: DB_CONNECTION.host,port: DB_CONNECTION.port},sock_options);
// ---- this section above from quotaguard documentation ---- //
}
setupConnection();
createConnection(DB_CONNECTION as MysqlConnectionOptions).then(async connection => {
// create express app
const app = express();
app.use(express.json());
// register express routes from defined application routes
Routes.forEach(route => {
(app as any)[route.method](route.route,(req: Request,res: Response,next: Function) => {
const result = (new (route.controller as any)())[route.action](req,res,next);
if (result instanceof Promise) {
result.then(result => result !== null && result !== undefined ? res.send(result) : undefined);
} else if (result !== null && result !== undefined) {
res.json(result);
}
});
});
// setup express app here
// start express server
app.listen(3000);
console.log("Express server has started on port 3000.
Open http://localhost:3000 to see results");
}).catch(error => console.log(error));
可能还有更好的软件包,但由于我从未处理过这种类型的东西,所以我只忽略了文档中的内容。
解决方法
所以我联系了 QuotaGuard,他们给了我一个有效的答案。答案如下:
但是,我们通常建议您使用我们的 QGTunnel 软件进行数据库连接。
QGTunnel 软件是一个包装程序,它从本地主机向您的应用程序提供套接字。然后您连接到该套接字,就好像它是您的数据库一样。以下是 QGTunnel 的一些设置说明。
-
Download QGTunnel 进入项目的根目录
-
登录我们的仪表板并设置隧道
使用 Heroku CLI,您可以使用以下命令登录我们的仪表板: heroku 插件:打开 quotaguardstatic
或者,如果您愿意,可以通过单击应用程序资源选项卡上的 QuotaGuard Static 从 Heroku 仪表板登录。
登录我们的仪表板后,在右上角的菜单中,转到设置。在左侧,点击隧道,然后点击创建隧道。
远程目标:tcp://hostname.for.your.server.com:3306 本地端口:3306 透明:真实 加密:假
此设置假设远程数据库服务器位于 hostname.for.your.server.com 并侦听端口 3306。这通常是默认端口。
本地端口是 QGTunnel 将侦听的端口号。在本例中我们将其设置为 3306,但如果您有另一个进程使用 3306,则可能需要更改它(即:3307)。
透明模式允许 QGTunnel 将 hostname.for.your.server.com 的 DNS 覆盖为 127.0.0.1,从而将流量重定向到 QGTunnel 软件。这意味着您可以连接到 hostname.for.your.server.com 或 127.0.0.1 以通过隧道进行连接。
加密模式可用于对数据进行端到端加密,但如果您的协议已经加密,则无需花时间进行设置。
- 更改您的代码以通过隧道进行连接 使用透明模式和匹配的本地和远程端口,您不需要更改代码。您也可以连接到 127.0.0.1:3306。
如果没有透明模式,您将需要连接到 127.0.0.1:3306。
- 更改您的启动代码。 更改启动应用程序的代码。在 heroku 中,这是通过 Procfile 完成的。基本上你只需要在你的启动代码前面加上“bin/qgtunnel”。
所以对于之前的 Procfile: web: your-application 你的论点 你现在想要: web: bin/qgtunnel your-application 你的论点
如果您没有 Procfile,则 heroku 将根据您使用的框架或语言使用默认设置代替 Procfile。您通常可以在 Heroku 仪表板中应用程序的概览选项卡上找到此信息。它通常位于“Dyno 信息”标题下。
- 提交并推送您的代码。 确保文件 bin/qgtunnel 已添加到您的存储库中。
如果您使用透明模式,请确保将 vendor/nss_wrapper/libnss_wrapper.so 也添加到您的存储库中。
- 如果您遇到问题,请启用环境变量 QGTUNNEL_DEBUG=true,然后在查看日志的同时重新启动您的应用程序。将日志中的任何信息发送给我。请遮盖所有敏感信息,包括您的 QuotaGuard 连接网址。
非常重要 7. 一切正常后,我建议您从我们的仪表板下载 QGTunnel 配置作为 .qgtunnel 文件并将其放在项目的根目录中。这可以防止您的项目在启动期间不依赖我们的网站。
这对我有用,而且我能够连接到我的数据库。