ConnectionConfig.js 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. var urlParse = require('url').parse;
  2. var ClientConstants = require('./protocol/constants/client');
  3. var Charsets = require('./protocol/constants/charsets');
  4. var SSLProfiles = null;
  5. module.exports = ConnectionConfig;
  6. function ConnectionConfig(options) {
  7. if (typeof options === 'string') {
  8. options = ConnectionConfig.parseUrl(options);
  9. }
  10. this.host = options.host || 'localhost';
  11. this.port = options.port || 3306;
  12. this.localAddress = options.localAddress;
  13. this.socketPath = options.socketPath;
  14. this.user = options.user || undefined;
  15. this.password = options.password || undefined;
  16. this.database = options.database;
  17. this.connectTimeout = (options.connectTimeout === undefined)
  18. ? (10 * 1000)
  19. : options.connectTimeout;
  20. this.insecureAuth = options.insecureAuth || false;
  21. this.supportBigNumbers = options.supportBigNumbers || false;
  22. this.bigNumberStrings = options.bigNumberStrings || false;
  23. this.dateStrings = options.dateStrings || false;
  24. this.debug = options.debug;
  25. this.trace = options.trace !== false;
  26. this.stringifyObjects = options.stringifyObjects || false;
  27. this.timezone = options.timezone || 'local';
  28. this.flags = options.flags || '';
  29. this.queryFormat = options.queryFormat;
  30. this.pool = options.pool || undefined;
  31. this.ssl = (typeof options.ssl === 'string')
  32. ? ConnectionConfig.getSSLProfile(options.ssl)
  33. : (options.ssl || false);
  34. this.localInfile = (options.localInfile === undefined)
  35. ? true
  36. : options.localInfile;
  37. this.multipleStatements = options.multipleStatements || false;
  38. this.typeCast = (options.typeCast === undefined)
  39. ? true
  40. : options.typeCast;
  41. if (this.timezone[0] === ' ') {
  42. // "+" is a url encoded char for space so it
  43. // gets translated to space when giving a
  44. // connection string..
  45. this.timezone = '+' + this.timezone.substr(1);
  46. }
  47. if (this.ssl) {
  48. // Default rejectUnauthorized to true
  49. this.ssl.rejectUnauthorized = this.ssl.rejectUnauthorized !== false;
  50. }
  51. this.maxPacketSize = 0;
  52. this.charsetNumber = (options.charset)
  53. ? ConnectionConfig.getCharsetNumber(options.charset)
  54. : options.charsetNumber || Charsets.UTF8_GENERAL_CI;
  55. // Set the client flags
  56. var defaultFlags = ConnectionConfig.getDefaultFlags(options);
  57. this.clientFlags = ConnectionConfig.mergeFlags(defaultFlags, options.flags);
  58. }
  59. ConnectionConfig.mergeFlags = function mergeFlags(defaultFlags, userFlags) {
  60. var allFlags = ConnectionConfig.parseFlagList(defaultFlags);
  61. var newFlags = ConnectionConfig.parseFlagList(userFlags);
  62. // Merge the new flags
  63. for (var flag in newFlags) {
  64. if (allFlags[flag] !== false) {
  65. allFlags[flag] = newFlags[flag];
  66. }
  67. }
  68. // Build flags
  69. var flags = 0x0;
  70. for (var flag in allFlags) {
  71. if (allFlags[flag]) {
  72. // TODO: Throw here on some future release
  73. flags |= ClientConstants['CLIENT_' + flag] || 0x0;
  74. }
  75. }
  76. return flags;
  77. };
  78. ConnectionConfig.getCharsetNumber = function getCharsetNumber(charset) {
  79. var num = Charsets[charset.toUpperCase()];
  80. if (num === undefined) {
  81. throw new TypeError('Unknown charset \'' + charset + '\'');
  82. }
  83. return num;
  84. };
  85. ConnectionConfig.getDefaultFlags = function getDefaultFlags(options) {
  86. var defaultFlags = [
  87. '-COMPRESS', // Compression protocol *NOT* supported
  88. '-CONNECT_ATTRS', // Does *NOT* send connection attributes in Protocol::HandshakeResponse41
  89. '+CONNECT_WITH_DB', // One can specify db on connect in Handshake Response Packet
  90. '+FOUND_ROWS', // Send found rows instead of affected rows
  91. '+IGNORE_SIGPIPE', // Don't issue SIGPIPE if network failures
  92. '+IGNORE_SPACE', // Let the parser ignore spaces before '('
  93. '+LOCAL_FILES', // Can use LOAD DATA LOCAL
  94. '+LONG_FLAG', // Longer flags in Protocol::ColumnDefinition320
  95. '+LONG_PASSWORD', // Use the improved version of Old Password Authentication
  96. '+MULTI_RESULTS', // Can handle multiple resultsets for COM_QUERY
  97. '+ODBC', // Special handling of ODBC behaviour
  98. '-PLUGIN_AUTH', // Does *NOT* support auth plugins
  99. '+PROTOCOL_41', // Uses the 4.1 protocol
  100. '+PS_MULTI_RESULTS', // Can handle multiple resultsets for COM_STMT_EXECUTE
  101. '+RESERVED', // Unused
  102. '+SECURE_CONNECTION', // Supports Authentication::Native41
  103. '+TRANSACTIONS' // Expects status flags
  104. ];
  105. if (options && options.localInfile !== undefined && !options.localInfile) {
  106. // Disable LOCAL modifier for LOAD DATA INFILE
  107. defaultFlags.push('-LOCAL_FILES');
  108. }
  109. if (options && options.multipleStatements) {
  110. // May send multiple statements per COM_QUERY and COM_STMT_PREPARE
  111. defaultFlags.push('+MULTI_STATEMENTS');
  112. }
  113. return defaultFlags;
  114. };
  115. ConnectionConfig.getSSLProfile = function getSSLProfile(name) {
  116. if (!SSLProfiles) {
  117. SSLProfiles = require('./protocol/constants/ssl_profiles');
  118. }
  119. var ssl = SSLProfiles[name];
  120. if (ssl === undefined) {
  121. throw new TypeError('Unknown SSL profile \'' + name + '\'');
  122. }
  123. return ssl;
  124. };
  125. ConnectionConfig.parseFlagList = function parseFlagList(flagList) {
  126. var allFlags = Object.create(null);
  127. if (!flagList) {
  128. return allFlags;
  129. }
  130. var flags = !Array.isArray(flagList)
  131. ? String(flagList || '').toUpperCase().split(/\s*,+\s*/)
  132. : flagList;
  133. for (var i = 0; i < flags.length; i++) {
  134. var flag = flags[i];
  135. var offset = 1;
  136. var state = flag[0];
  137. if (state === undefined) {
  138. // TODO: throw here on some future release
  139. continue;
  140. }
  141. if (state !== '-' && state !== '+') {
  142. offset = 0;
  143. state = '+';
  144. }
  145. allFlags[flag.substr(offset)] = state === '+';
  146. }
  147. return allFlags;
  148. };
  149. ConnectionConfig.parseUrl = function(url) {
  150. url = urlParse(url, true);
  151. var options = {
  152. host : url.hostname,
  153. port : url.port,
  154. database : url.pathname.substr(1)
  155. };
  156. if (url.auth) {
  157. var auth = url.auth.split(':');
  158. options.user = auth.shift();
  159. options.password = auth.join(':');
  160. }
  161. if (url.query) {
  162. for (var key in url.query) {
  163. var value = url.query[key];
  164. try {
  165. // Try to parse this as a JSON expression first
  166. options[key] = JSON.parse(value);
  167. } catch (err) {
  168. // Otherwise assume it is a plain string
  169. options[key] = value;
  170. }
  171. }
  172. }
  173. return options;
  174. };