在使用了fastify-mysql的项目开发中,发现连接数据库时是传的字符串mysql://root@localhost/mysql
,和url地址类似,百思不得其解,正常的配置都是有多个选项的一个对象,那么常规理解就是字符串的位置一定对应选项中每个字段,那么,对应关系是如何的呢?源码走起……
源码分析
fastify-mysql传的参数类型如下,连接类型有两种,连接池和普通连接,默认连接类型是 pool
// node_modules/fastify-mysql/index.d.ts
export type ConnectionType = "connection" | "pool";
export interface MySQLOptions extends PoolOptions, ConnectionOptions {
type?: ConnectionType;
name?: string;
promise?: boolean;
connectionString?: string;
}
fastify-mysql底层使用的是mysql2,从fastify-mysql源码中得知,当 ConnectionType
为 pool
时,调用的是 mysql.createPool
方法,为 connection
时,调用的是 mysql.createConnection
方法
exports.createPool = function(config) {
const PoolConfig = require('./lib/pool_config.js');
return new Pool({ config: new PoolConfig(config) });
};
再进一步是在 pool_config.js
中处理我们传过来的 connectionstring
=== line-highlight
data-line: 9-11
===
// node_modules/mysql2/lib/pool_config.js
const ConnectionConfig = require('./connection_config.js');
class PoolConfig {
constructor(options) {
if (typeof options === 'string') {
options = ConnectionConfig.parseUrl(options);
}
this.connectionConfig = new ConnectionConfig(options);
……
}
}
module.exports = PoolConfig;
接着在connection_config.js里面查找,发现了一个 parseUrl
的静态方法,mysql://root@localhost/mysql对应连接数据库配置参数的对应关系就出来了
对应关系
static parseUrl(url) {
url = urlParse(url, true);
const options = {
host: url.hostname,
port: url.port,
database: url.pathname.substr(1)
};
if (url.auth) {
const auth = url.auth.split(':');
options.user = auth[0];
options.password = auth[1];
}
if (url.query) {
for (const key in url.query) {
const value = url.query[key];
try {
// Try to parse this as a JSON expression first
options[key] = JSON.parse(value);
} catch (err) {
// Otherwise assume it is a plain string
options[key] = value;
}
}
}
return options;
}
URL额外补充
url是统一资源定位符(Uniform Resource Locator)的缩写,他的格式为:
[comment]: <> (标准格式)
[协议类型]://[服务器地址]:[端口号]/[资源层级UNIX文件路径][文件名]?[查询]#[片段ID]
[comment]: <> (完整格式)
[协议类型]://[访问资源需要的凭证信息]@[服务器地址]:[端口号]/[资源层级UNIX文件路径][文件名]?[查询]#[片段ID]
[comment]: <> (其中[访问凭证信息]、[端口号]、[查询]、[片段ID]属于选填项)
统一资源定位符不但被用作网页地址,JDBC 客户端也使用统一资源定位符连接其数据库服务器。作为对比,ODBC 的连接字符串作用相同,但并不采用 URL 格式,而是分号和等号分隔的键值对。右侧是一个 Oracle 数据库的统一资源定位符:jdbc:datadirect:oracle://myserver:1521;sid=testdb
最终呈现
假设有这样一个地址:mysql://user:password@host:3306/database?charset=utf8
,Node环境解析如下
注意,传统的urlObject方式(即以下方式)在v11.0.0开始弃用,新的方式为new URL(<URL>)
const urlParse = require('url').parse;
urlParse('mysql://user:password@host:3306/database?charset=utf8')
Url {
protocol: 'mysql:',
slashes: true,
auth: 'user:password',
host: 'host:3306',
port: '3306',
hostname: 'host',
hash: null,
search: '?charset=utf8',
query: 'charset=utf8',
pathname: '/database',
path: '/database?charset=utf8',
href: 'mysql://user:password@host:3306/database?charset=utf8'
}
// 通过上面的parseUrl解析之后得到
{
host: 'host',
port: '3306',
database: 'database',
user: 'user',
password: 'password',
charset: 'utf8'
}
总结
所以,我这一顿操作分析了个寂寞??????
评论 (0)