MCPcopy
hub / github.com/caddyserver/caddy / parseEnvFile

Function parseEnvFile

cmd/main.go:385–450  ·  view source on GitHub ↗

parseEnvFile parses an env file from KEY=VALUE format. It's pretty naive. Limited value quotation is supported, but variable and command expansions are not supported.

(envInput io.Reader)

Source from the content-addressed store, hash-verified

383// It's pretty naive. Limited value quotation is supported,
384// but variable and command expansions are not supported.
385func parseEnvFile(envInput io.Reader) (map[string]string, error) {
386 envMap := make(map[string]string)
387
388 scanner := bufio.NewScanner(envInput)
389 var lineNumber int
390
391 for scanner.Scan() {
392 line := strings.TrimSpace(scanner.Text())
393 lineNumber++
394
395 // skip empty lines and lines starting with comment
396 if line == "" || strings.HasPrefix(line, "#") {
397 continue
398 }
399
400 // split line into key and value
401 before, after, isCut := strings.Cut(line, "=")
402 if !isCut {
403 return nil, fmt.Errorf("can't parse line %d; line should be in KEY=VALUE format", lineNumber)
404 }
405 key, val := before, after
406
407 // sometimes keys are prefixed by "export " so file can be sourced in bash; ignore it here
408 key = strings.TrimPrefix(key, "export ")
409
410 // validate key and value
411 if key == "" {
412 return nil, fmt.Errorf("missing or empty key on line %d", lineNumber)
413 }
414 if strings.Contains(key, " ") {
415 return nil, fmt.Errorf("invalid key on line %d: contains whitespace: %s", lineNumber, key)
416 }
417 if strings.HasPrefix(val, " ") || strings.HasPrefix(val, "\t") {
418 return nil, fmt.Errorf("invalid value on line %d: whitespace before value: '%s'", lineNumber, val)
419 }
420
421 // remove any trailing comment after value
422 if commentStart, _, found := strings.Cut(val, "#"); found {
423 val = strings.TrimRight(commentStart, " \t")
424 }
425
426 // quoted value: support newlines
427 if strings.HasPrefix(val, `"`) || strings.HasPrefix(val, "'") {
428 quote := string(val[0])
429 for !strings.HasSuffix(line, quote) || strings.HasSuffix(line, `\`+quote) {
430 val = strings.ReplaceAll(val, `\`+quote, quote)
431 if !scanner.Scan() {
432 break
433 }
434 lineNumber++
435 line = strings.ReplaceAll(scanner.Text(), `\`+quote, quote)
436 val += "\n" + line
437 }
438 val = strings.TrimPrefix(val, quote)
439 val = strings.TrimSuffix(val, quote)
440 }
441
442 envMap[key] = val

Callers 2

TestParseEnvFileFunction · 0.85
loadEnvFromFileFunction · 0.85

Calls 2

ReplaceAllMethod · 0.80
ErrMethod · 0.80

Tested by 1

TestParseEnvFileFunction · 0.68