Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 0f785ff

Browse files
sklarsapuzpuzpuz
andauthored
fix(client): modify config parsing behavior to match other clients (#28)
Co-authored-by: Andrey Pechkurov <apechkurov@gmail.com>
1 parent 8a27774 commit 0f785ff

File tree

5 files changed

+93
-79
lines changed

5 files changed

+93
-79
lines changed

‎README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ Features:
1111
* Optimized for batch writes.
1212
* Supports TLS encryption and ILP authentication.
1313
* Automatic write retries and connection reuse for ILP over HTTP.
14-
* Tested against QuestDB 7.3.11 and newer versions.
14+
* Tested against QuestDB 7.3.10 and newer versions.
1515

1616
New in v3:
1717
* Supports ILP over HTTP using the same client semantics

‎conf_parse.go‎

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ func confFromStr(conf string) (*lineSenderConfig, error) {
6060
}
6161

6262
for k, v := range data.KeyValuePairs {
63-
switch strings.ToLower(k) {
63+
switch k {
6464
case "addr":
6565
senderConf.address = v
6666
case "username":
@@ -86,6 +86,10 @@ func confFromStr(conf string) (*lineSenderConfig, error) {
8686
default:
8787
panic("add a case for " + k)
8888
}
89+
case "token_x":
90+
case "token_y":
91+
// Some clients require public key.
92+
// But since Go sender doesn't need it, we ignore the values.
8993
case "auto_flush":
9094
if v == "off" {
9195
senderConf.autoFlushRows = 0
@@ -166,9 +170,8 @@ func parseConfigStr(conf string) (configData, error) {
166170
KeyValuePairs: map[string]string{},
167171
}
168172

169-
nextRune rune
170-
isEscaping bool
171-
hasTrailingSemicolon bool
173+
nextRune rune
174+
isEscaping bool
172175
)
173176

174177
schemaStr, conf, found := strings.Cut(conf, "::")
@@ -182,10 +185,8 @@ func parseConfigStr(conf string) (configData, error) {
182185
return result, NewInvalidConfigStrError("'addr' key not found")
183186
}
184187

185-
if strings.HasSuffix(conf, ";") {
186-
hasTrailingSemicolon = true
187-
} else {
188-
conf = conf + ";" // add trailing semicolon if it doesn't exist
188+
if !strings.HasSuffix(conf, ";") {
189+
return result, NewInvalidConfigStrError("trailing semicolon ';' required")
189190
}
190191

191192
keyValueStr := []rune(conf)
@@ -198,7 +199,7 @@ func parseConfigStr(conf string) (configData, error) {
198199
switch rune {
199200
case ';':
200201
if isKey {
201-
if nextRune == 0 &&!hasTrailingSemicolon{
202+
if nextRune == 0 {
202203
return result, NewInvalidConfigStrError("unexpected end of string")
203204
}
204205
return result, NewInvalidConfigStrError("invalid key character ';'")

‎conf_test.go‎

Lines changed: 48 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ func TestParserHappyCases(t *testing.T) {
5454
testCases := []parseConfigTestCase{
5555
{
5656
name: "http and ipv4 address",
57-
config: fmt.Sprintf("http::addr=%s", addr),
57+
config: fmt.Sprintf("http::addr=%s;", addr),
5858
expected: qdb.ConfigData{
5959
Schema: "http",
6060
KeyValuePairs: map[string]string{
@@ -74,7 +74,7 @@ func TestParserHappyCases(t *testing.T) {
7474
},
7575
{
7676
name: "tcp and address",
77-
config: fmt.Sprintf("tcp::addr=%s", addr),
77+
config: fmt.Sprintf("tcp::addr=%s;", addr),
7878
expected: qdb.ConfigData{
7979
Schema: "tcp",
8080
KeyValuePairs: map[string]string{
@@ -84,7 +84,7 @@ func TestParserHappyCases(t *testing.T) {
8484
},
8585
{
8686
name: "http and username/password",
87-
config: fmt.Sprintf("http::addr=%s;username=%s;password=%s", addr, user, pass),
87+
config: fmt.Sprintf("http::addr=%s;username=%s;password=%s;", addr, user, pass),
8888
expected: qdb.ConfigData{
8989
Schema: "http",
9090
KeyValuePairs: map[string]string{
@@ -107,7 +107,7 @@ func TestParserHappyCases(t *testing.T) {
107107
},
108108
{
109109
name: "tcp with key and user",
110-
config: fmt.Sprintf("tcp::addr=%s;token=%s;username=%s", addr, token, user),
110+
config: fmt.Sprintf("tcp::addr=%s;token=%s;username=%s;", addr, token, user),
111111
expected: qdb.ConfigData{
112112
Schema: "tcp",
113113
KeyValuePairs: map[string]string{
@@ -119,7 +119,7 @@ func TestParserHappyCases(t *testing.T) {
119119
},
120120
{
121121
name: "https with min_throughput",
122-
config: fmt.Sprintf("https::addr=%s;min_throughput=%d", addr, min_throughput),
122+
config: fmt.Sprintf("https::addr=%s;min_throughput=%d;", addr, min_throughput),
123123
expected: qdb.ConfigData{
124124
Schema: "https",
125125
KeyValuePairs: map[string]string{
@@ -130,7 +130,7 @@ func TestParserHappyCases(t *testing.T) {
130130
},
131131
{
132132
name: "https with min_throughput, init_buf_size and tls_verify=unsafe_off",
133-
config: fmt.Sprintf("https::addr=%s;min_throughput=%d;init_buf_size=%d;tls_verify=unsafe_off", addr, min_throughput, 1024),
133+
config: fmt.Sprintf("https::addr=%s;min_throughput=%d;init_buf_size=%d;tls_verify=unsafe_off;", addr, min_throughput, 1024),
134134
expected: qdb.ConfigData{
135135
Schema: "https",
136136
KeyValuePairs: map[string]string{
@@ -143,7 +143,7 @@ func TestParserHappyCases(t *testing.T) {
143143
},
144144
{
145145
name: "tcps with tls_verify=unsafe_off",
146-
config: fmt.Sprintf("tcps::addr=%s;tls_verify=unsafe_off", addr),
146+
config: fmt.Sprintf("tcps::addr=%s;tls_verify=unsafe_off;", addr),
147147
expected: qdb.ConfigData{
148148
Schema: "tcps",
149149
KeyValuePairs: map[string]string{
@@ -154,7 +154,7 @@ func TestParserHappyCases(t *testing.T) {
154154
},
155155
{
156156
name: "http with min_throughput, request_timeout, and retry_timeout",
157-
config: fmt.Sprintf("http::addr=%s;min_throughput=%d;request_timeout=%d;retry_timeout=%d",
157+
config: fmt.Sprintf("http::addr=%s;min_throughput=%d;request_timeout=%d;retry_timeout=%d;",
158158
addr, min_throughput, request_timeout.Milliseconds(), retry_timeout.Milliseconds()),
159159
expected: qdb.ConfigData{
160160
Schema: "http",
@@ -168,7 +168,7 @@ func TestParserHappyCases(t *testing.T) {
168168
},
169169
{
170170
name: "tcp with tls_verify=on",
171-
config: fmt.Sprintf("tcp::addr=%s;tls_verify=on", addr),
171+
config: fmt.Sprintf("tcp::addr=%s;tls_verify=on;", addr),
172172
expected: qdb.ConfigData{
173173
Schema: "tcp",
174174
KeyValuePairs: map[string]string{
@@ -177,18 +177,6 @@ func TestParserHappyCases(t *testing.T) {
177177
},
178178
},
179179
},
180-
{
181-
name: "password with an escaped semicolon",
182-
config: fmt.Sprintf("http::addr=%s;username=%s;password=pass;;word", addr, user),
183-
expected: qdb.ConfigData{
184-
Schema: "http",
185-
KeyValuePairs: map[string]string{
186-
"addr": addr,
187-
"username": user,
188-
"password": "pass;word",
189-
},
190-
},
191-
},
192180
{
193181
name: "password with an escaped semicolon (ending with a ';')",
194182
config: fmt.Sprintf("http::addr=%s;username=%s;password=pass;;word;", addr, user),
@@ -215,7 +203,7 @@ func TestParserHappyCases(t *testing.T) {
215203
},
216204
{
217205
name: "equal sign in password",
218-
config: fmt.Sprintf("http::addr=%s;username=%s;password=pass=word", addr, user),
206+
config: fmt.Sprintf("http::addr=%s;username=%s;password=pass=word;", addr, user),
219207
expected: qdb.ConfigData{
220208
Schema: "http",
221209
KeyValuePairs: map[string]string{
@@ -253,15 +241,10 @@ func TestParserPathologicalCases(t *testing.T) {
253241
config: "http::",
254242
expectedErrMsgContains: "'addr' key not found",
255243
},
256-
{
257-
name: "unescaped semicolon in password leads to unexpected end of string",
258-
config: "http::addr=localhost:9000;username=test;password=pass;word",
259-
expectedErrMsgContains: "unexpected end of string",
260-
},
261244
{
262245
name: "unescaped semicolon in password leads to invalid key character",
263246
config: "http::addr=localhost:9000;username=test;password=pass;word;",
264-
expectedErrMsgContains: "invalid key character ';'",
247+
expectedErrMsgContains: "unexpected end of",
265248
},
266249
}
267250

@@ -299,7 +282,17 @@ func TestHappyCasesFromConf(t *testing.T) {
299282
testCases := []configTestCase{
300283
{
301284
name: "user and token",
302-
config: fmt.Sprintf("tcp::addr=%s;username=%s;token=%s",
285+
config: fmt.Sprintf("tcp::addr=%s;username=%s;token=%s;",
286+
addr, user, token),
287+
expectedOpts: []qdb.LineSenderOption{
288+
qdb.WithTcp(),
289+
qdb.WithAddress(addr),
290+
qdb.WithAuth(user, token),
291+
},
292+
},
293+
{
294+
name: "token_x and token_y (ignored)",
295+
config: fmt.Sprintf("tcp::addr=%s;username=%s;token=%s;token_x=xyz;token_y=xyz;",
303296
addr, user, token),
304297
expectedOpts: []qdb.LineSenderOption{
305298
qdb.WithTcp(),
@@ -309,7 +302,7 @@ func TestHappyCasesFromConf(t *testing.T) {
309302
},
310303
{
311304
name: "init_buf_size and max_buf_size",
312-
config: fmt.Sprintf("tcp::addr=%s;init_buf_size=%d;max_buf_size=%d",
305+
config: fmt.Sprintf("tcp::addr=%s;init_buf_size=%d;max_buf_size=%d;",
313306
addr, initBufSize, maxBufSize),
314307
expectedOpts: []qdb.LineSenderOption{
315308
qdb.WithTcp(),
@@ -320,7 +313,7 @@ func TestHappyCasesFromConf(t *testing.T) {
320313
},
321314
{
322315
name: "with tls",
323-
config: fmt.Sprintf("tcp::addr=%s;tls_verify=on",
316+
config: fmt.Sprintf("tcp::addr=%s;tls_verify=on;",
324317
addr),
325318
expectedOpts: []qdb.LineSenderOption{
326319
qdb.WithTcp(),
@@ -330,7 +323,7 @@ func TestHappyCasesFromConf(t *testing.T) {
330323
},
331324
{
332325
name: "with tls and unsafe_off",
333-
config: fmt.Sprintf("tcp::addr=%s;tls_verify=unsafe_off",
326+
config: fmt.Sprintf("tcp::addr=%s;tls_verify=unsafe_off;",
334327
addr),
335328
expectedOpts: []qdb.LineSenderOption{
336329
qdb.WithTcp(),
@@ -340,7 +333,7 @@ func TestHappyCasesFromConf(t *testing.T) {
340333
},
341334
{
342335
name: "request_timeout and retry_timeout milli conversion",
343-
config: fmt.Sprintf("http::addr=%s;request_timeout=%d;retry_timeout=%d",
336+
config: fmt.Sprintf("http::addr=%s;request_timeout=%d;retry_timeout=%d;",
344337
addr, requestTimeout.Milliseconds(), retryTimeout.Milliseconds()),
345338
expectedOpts: []qdb.LineSenderOption{
346339
qdb.WithHttp(),
@@ -351,7 +344,7 @@ func TestHappyCasesFromConf(t *testing.T) {
351344
},
352345
{
353346
name: "password before username",
354-
config: fmt.Sprintf("http::addr=%s;password=%s;username=%s",
347+
config: fmt.Sprintf("http::addr=%s;password=%s;username=%s;",
355348
addr, pass, user),
356349
expectedOpts: []qdb.LineSenderOption{
357350
qdb.WithHttp(),
@@ -361,7 +354,7 @@ func TestHappyCasesFromConf(t *testing.T) {
361354
},
362355
{
363356
name: "min_throughput",
364-
config: fmt.Sprintf("http::addr=%s;min_throughput=%d",
357+
config: fmt.Sprintf("http::addr=%s;min_throughput=%d;",
365358
addr, minThroughput),
366359
expectedOpts: []qdb.LineSenderOption{
367360
qdb.WithHttp(),
@@ -371,7 +364,7 @@ func TestHappyCasesFromConf(t *testing.T) {
371364
},
372365
{
373366
name: "bearer token",
374-
config: fmt.Sprintf("http::addr=%s;token=%s",
367+
config: fmt.Sprintf("http::addr=%s;token=%s;",
375368
addr, token),
376369
expectedOpts: []qdb.LineSenderOption{
377370
qdb.WithHttp(),
@@ -381,7 +374,7 @@ func TestHappyCasesFromConf(t *testing.T) {
381374
},
382375
{
383376
name: "auto flush",
384-
config: fmt.Sprintf("http::addr=%s;auto_flush_rows=100;auto_flush_interval=1000",
377+
config: fmt.Sprintf("http::addr=%s;auto_flush_rows=100;auto_flush_interval=1000;",
385378
addr),
386379
expectedOpts: []qdb.LineSenderOption{
387380
qdb.WithHttp(),
@@ -416,44 +409,54 @@ func TestPathologicalCasesFromConf(t *testing.T) {
416409
},
417410
{
418411
name: "invalid schema",
419-
config: "foobar::addr=localhost:1111",
412+
config: "foobar::addr=localhost:1111;",
420413
expectedErrMsgContains: "invalid schema",
421414
},
422415
{
423416
name: "invalid tls_verify 1",
424-
config: "tcp::addr=localhost:1111;tls_verify=invalid",
417+
config: "tcp::addr=localhost:1111;tls_verify=invalid;",
425418
expectedErrMsgContains: "invalid tls_verify",
426419
},
427420
{
428421
name: "invalid tls_verify 2",
429-
config: "http::addr=localhost:1111;tls_verify=invalid",
422+
config: "http::addr=localhost:1111;tls_verify=invalid;",
430423
expectedErrMsgContains: "invalid tls_verify",
431424
},
432425
{
433426
name: "unsupported option",
434-
config: "tcp::addr=localhost:1111;unsupported_option=invalid",
427+
config: "tcp::addr=localhost:1111;unsupported_option=invalid;",
435428
expectedErrMsgContains: "unsupported option",
436429
},
437430
{
438431
name: "invalid auto_flush",
439-
config: "http::addr=localhost:1111;auto_flush=invalid",
432+
config: "http::addr=localhost:1111;auto_flush=invalid;",
440433
expectedErrMsgContains: "invalid auto_flush",
441434
},
442435
{
443436
name: "invalid auto_flush_rows",
444-
config: "http::addr=localhost:1111;auto_flush_rows=invalid",
437+
config: "http::addr=localhost:1111;auto_flush_rows=invalid;",
445438
expectedErrMsgContains: "invalid auto_flush_rows",
446439
},
447440
{
448441
name: "invalid auto_flush_interval",
449-
config: "http::addr=localhost:1111;auto_flush_interval=invalid",
442+
config: "http::addr=localhost:1111;auto_flush_interval=invalid;",
450443
expectedErrMsgContains: "invalid auto_flush_interval",
451444
},
452445
{
453446
name: "unsupported option",
454-
config: "http::addr=localhost:1111;unsupported_option=invalid",
447+
config: "http::addr=localhost:1111;unsupported_option=invalid;",
448+
expectedErrMsgContains: "unsupported option",
449+
},
450+
{
451+
name: "case-sensitive values",
452+
config: "http::aDdr=localhost:9000;",
455453
expectedErrMsgContains: "unsupported option",
456454
},
455+
{
456+
name: "trailing semicolon required",
457+
config: "http::addr=localhost:9000",
458+
expectedErrMsgContains: "trailing semicolon",
459+
},
457460
}
458461

459462
for _, tc := range testCases {

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /