@@ -20,7 +20,6 @@ import (
20
20
"os"
21
21
"regexp"
22
22
"strings"
23
- "unicode"
24
23
25
24
"github.com/go-kit/log/level"
26
25
"github.com/prometheus/client_golang/prometheus"
@@ -173,196 +172,3 @@ func getDataSources() ([]string, error) {
173
172
174
173
return []string {dsn }, nil
175
174
}
176
-
177
- // dsn represents a parsed datasource. It contains fields for the individual connection components.
178
- type dsn struct {
179
- scheme string
180
- username string
181
- password string
182
- host string
183
- path string
184
- query string
185
- }
186
-
187
- // String makes a dsn safe to print by excluding any passwords. This allows dsn to be used in
188
- // strings and log messages without needing to call a redaction function first.
189
- func (d dsn ) String () string {
190
- if d .password != "" {
191
- return fmt .Sprintf ("%s://%s:******@%s%s?%s" , d .scheme , d .username , d .host , d .path , d .query )
192
- }
193
-
194
- if d .username != "" {
195
- return fmt .Sprintf ("%s://%s@%s%s?%s" , d .scheme , d .username , d .host , d .path , d .query )
196
- }
197
-
198
- return fmt .Sprintf ("%s://%s%s?%s" , d .scheme , d .host , d .path , d .query )
199
- }
200
-
201
- // dsnFromString parses a connection string into a dsn. It will attempt to parse the string as
202
- // a URL and as a set of key=value pairs. If both attempts fail, dsnFromString will return an error.
203
- func dsnFromString (in string ) (dsn , error ) {
204
- if strings .HasPrefix (in , "postgresql://" ) {
205
- return dsnFromURL (in )
206
- }
207
-
208
- // Try to parse as key=value pairs
209
- d , err := dsnFromKeyValue (in )
210
- if err == nil {
211
- return d , nil
212
- }
213
-
214
- return dsn {}, fmt .Errorf ("could not understand DSN" )
215
- }
216
-
217
- // dsnFromURL parses the input as a URL and returns the dsn representation.
218
- func dsnFromURL (in string ) (dsn , error ) {
219
- u , err := url .Parse (in )
220
- if err != nil {
221
- return dsn {}, err
222
- }
223
- pass , _ := u .User .Password ()
224
- user := u .User .Username ()
225
-
226
- query := u .Query ()
227
-
228
- if queryPass := query .Get ("password" ); queryPass != "" {
229
- if pass == "" {
230
- pass = queryPass
231
- }
232
- }
233
- query .Del ("password" )
234
-
235
- if queryUser := query .Get ("user" ); queryUser != "" {
236
- if user == "" {
237
- user = queryUser
238
- }
239
- }
240
- query .Del ("user" )
241
-
242
- d := dsn {
243
- scheme : u .Scheme ,
244
- username : user ,
245
- password : pass ,
246
- host : u .Host ,
247
- path : u .Path ,
248
- query : query .Encode (),
249
- }
250
-
251
- return d , nil
252
- }
253
-
254
- // dsnFromKeyValue parses the input as a set of key=value pairs and returns the dsn representation.
255
- func dsnFromKeyValue (in string ) (dsn , error ) {
256
- // Attempt to confirm at least one key=value pair before starting the rune parser
257
- connstringRe := regexp .MustCompile (`^ *[a-zA-Z0-9]+ *= *[^= ]+` )
258
- if ! connstringRe .MatchString (in ) {
259
- return dsn {}, fmt .Errorf ("input is not a key-value DSN" )
260
- }
261
-
262
- // Anything other than known fields should be part of the querystring
263
- query := url.Values {}
264
-
265
- pairs , err := parseKeyValue (in )
266
- if err != nil {
267
- return dsn {}, fmt .Errorf ("failed to parse key-value DSN: %v" , err )
268
- }
269
-
270
- // Build the dsn from the key=value pairs
271
- d := dsn {
272
- scheme : "postgresql" ,
273
- }
274
-
275
- hostname := ""
276
- port := ""
277
-
278
- for k , v := range pairs {
279
- switch k {
280
- case "host" :
281
- hostname = v
282
- case "port" :
283
- port = v
284
- case "user" :
285
- d .username = v
286
- case "password" :
287
- d .password = v
288
- default :
289
- query .Set (k , v )
290
- }
291
- }
292
-
293
- if hostname == "" {
294
- hostname = "localhost"
295
- }
296
-
297
- if port == "" {
298
- d .host = hostname
299
- } else {
300
- d .host = fmt .Sprintf ("%s:%s" , hostname , port )
301
- }
302
-
303
- d .query = query .Encode ()
304
-
305
- return d , nil
306
- }
307
-
308
- // parseKeyValue is a key=value parser. It loops over each rune to split out keys and values
309
- // and attempting to honor quoted values. parseKeyValue will return an error if it is unable
310
- // to properly parse the input.
311
- func parseKeyValue (in string ) (map [string ]string , error ) {
312
- out := map [string ]string {}
313
-
314
- inPart := false
315
- inQuote := false
316
- part := []rune {}
317
- key := ""
318
- for _ , c := range in {
319
- switch {
320
- case unicode .In (c , unicode .Quotation_Mark ):
321
- if inQuote {
322
- inQuote = false
323
- } else {
324
- inQuote = true
325
- }
326
- case unicode .In (c , unicode .White_Space ):
327
- if inPart {
328
- if inQuote {
329
- part = append (part , c )
330
- } else {
331
- // Are we finishing a key=value?
332
- if key == "" {
333
- return out , fmt .Errorf ("invalid input" )
334
- }
335
- out [key ] = string (part )
336
- inPart = false
337
- part = []rune {}
338
- }
339
- } else {
340
- // Are we finishing a key=value?
341
- if key == "" {
342
- return out , fmt .Errorf ("invalid input" )
343
- }
344
- out [key ] = string (part )
345
- inPart = false
346
- part = []rune {}
347
- // Do something with the value
348
- }
349
- case c == '=' :
350
- if inPart {
351
- inPart = false
352
- key = string (part )
353
- part = []rune {}
354
- } else {
355
- return out , fmt .Errorf ("invalid input" )
356
- }
357
- default :
358
- inPart = true
359
- part = append (part , c )
360
- }
361
- }
362
-
363
- if key != "" && len (part ) > 0 {
364
- out [key ] = string (part )
365
- }
366
-
367
- return out , nil
368
- }
0 commit comments