From a8e4e565b2fc0b785c3dc2eca4cbe3942c86c7ae Mon Sep 17 00:00:00 2001 From: Jakub Bednar Date: Thu, 25 Jun 2020 10:51:07 +0200 Subject: [PATCH 1/3] fix: serialization of `\n`, `\r` and `\t` to Line Protocol --- CHANGELOG.md | 4 ++ packages/core/src/util/escape.ts | 58 ++++++++++++++++++-- packages/core/test/fixture/escapeTables.json | 10 +++- 3 files changed, 64 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4eff31c77..26fcd2eaa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ 1. [#207](https://github.com/influxdata/influxdb-client-js/pull/207): Explain the significance of the precision argument in write example. +### Bug Fixes + +1. [#205](https://github.com/influxdata/influxdb-client-js/pull/205): Fixed serialization of `\n`, `\r` and `\t` to Line Protocol + ## 1.4.0 [2020-06-19] ### Features diff --git a/packages/core/src/util/escape.ts b/packages/core/src/util/escape.ts index f1035ad3c..593f4577a 100644 --- a/packages/core/src/util/escape.ts +++ b/packages/core/src/util/escape.ts @@ -35,8 +35,13 @@ const escapeChar = '\\' class Escaper { private _re: RegExp - constructor(chars: string[], private wrap: string = '') { - const patterns = chars.join('').replace(reEscape, '\\$&') + constructor( + private config: {[p: string]: EscaperConfig} = {}, + private wrap: string = '' + ) { + const patterns = Object.keys(config) + .join('|') + .replace(reEscape, '\\$&') this._re = new RegExp('[' + patterns + ']', 'g') } @@ -51,7 +56,11 @@ class Escaper { let match = this._re.exec(val) while (match) { - escapedVal += val.slice(chunkIndex, match.index) + escapeChar + match[0] + const matched = match[0] + const toEscape = this.config[matched].escapeChar + const toReplace = this.config[matched].replaceChar + escapedVal += val.slice(chunkIndex, match.index) + escapedVal += toReplace != undefined ? toReplace : toEscape + matched chunkIndex = this._re.lastIndex match = this._re.exec(val) } @@ -68,21 +77,58 @@ class Escaper { } } +class EscaperConfig { + escapeChar?: string + replaceChar?: string + + constructor(escapeChar?: string, replaceChar?: string) { + this.escapeChar = escapeChar + this.replaceChar = replaceChar + } +} + +const escaperConfig = new EscaperConfig(escapeChar) + const bindEsc = (e: Escaper): ((val: string) => string) => e.escape.bind(e) export const escape = { /** * Measurement escapes measurement names. */ - measurement: bindEsc(new Escaper([',', ' '])), + measurement: bindEsc( + new Escaper({ + ',': escaperConfig, + ' ': escaperConfig, + '\n': new EscaperConfig(undefined, '\\n'), + '\r': new EscaperConfig(undefined, '\\r'), + '\t': new EscaperConfig(undefined, '\\t'), + }) + ), /** * Quoted escapes quoted values, such as database names. */ - quoted: bindEsc(new Escaper(['"', '\\\\'], '"')), + quoted: bindEsc( + new Escaper( + { + '"': escaperConfig, + '\\\\': escaperConfig, + }, + '"' + ) + ), /** * TagEscaper escapes tag keys, tag values, and field keys. */ - tag: bindEsc(new Escaper([',', '=', ' '])), + tag: bindEsc( + new Escaper({ + ',': escaperConfig, + '=': escaperConfig, + ' ': escaperConfig, + '\n': new EscaperConfig(undefined, '\\n'), + '\r': new EscaperConfig(undefined, '\\r'), + '\t': new EscaperConfig(undefined, '\\t'), + }) + ), } diff --git a/packages/core/test/fixture/escapeTables.json b/packages/core/test/fixture/escapeTables.json index ea0c27609..6514b98b0 100644 --- a/packages/core/test/fixture/escapeTables.json +++ b/packages/core/test/fixture/escapeTables.json @@ -8,14 +8,20 @@ ["a=b", "a\\=b"], ["a b", "a\\ b"], ["a b=c", "a\\ b\\=c"], - ["'a' \\b=c\\,\\\\\"d\"", "'a'\\ \\b\\=c\\\\,\\\\\"d\""] + ["'a' \\b=c\\,\\\\\"d\"", "'a'\\ \\b\\=c\\\\,\\\\\"d\""], + ["new\nline", "new\\nline"], + ["carriage\rreturn", "carriage\\rreturn"], + ["t\tab", "t\\tab"] ], "measurement": [ ["ab", "ab"], ["a,", "a\\,"], ["a,b", "a\\,b"], ["a b", "a\\ b"], - ["a b,c", "a\\ b\\,c"] + ["a b,c", "a\\ b\\,c"], + ["new\nline", "new\\nline"], + ["carriage\rreturn", "carriage\\rreturn"], + ["t\tab", "t\\tab"] ], "quoted": [ ["ab", "\"ab\""], From af1635c894ef909fea75196f9ff8c53a126f06c1 Mon Sep 17 00:00:00 2001 From: Jakub Bednar Date: Thu, 25 Jun 2020 11:08:41 +0200 Subject: [PATCH 2/3] fix: config is required --- packages/core/src/util/escape.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/util/escape.ts b/packages/core/src/util/escape.ts index 593f4577a..16afdd9cd 100644 --- a/packages/core/src/util/escape.ts +++ b/packages/core/src/util/escape.ts @@ -36,7 +36,7 @@ class Escaper { private _re: RegExp constructor( - private config: {[p: string]: EscaperConfig} = {}, + private config: {[p: string]: EscaperConfig}, private wrap: string = '' ) { const patterns = Object.keys(config) From 7e35d26cc92a2a50c3ea4d1becd9973cc1c6e837 Mon Sep 17 00:00:00 2001 From: Jakub Bednar Date: Fri, 26 Jun 2020 09:23:06 +0200 Subject: [PATCH 3/3] chore: clarify that `=` is legal character in measurement name --- packages/core/test/fixture/escapeTables.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/core/test/fixture/escapeTables.json b/packages/core/test/fixture/escapeTables.json index 6514b98b0..f9a125df0 100644 --- a/packages/core/test/fixture/escapeTables.json +++ b/packages/core/test/fixture/escapeTables.json @@ -21,7 +21,8 @@ ["a b,c", "a\\ b\\,c"], ["new\nline", "new\\nline"], ["carriage\rreturn", "carriage\\rreturn"], - ["t\tab", "t\\tab"] + ["t\tab", "t\\tab"], + ["equ=al", "equ=al"] ], "quoted": [ ["ab", "\"ab\""],