Dotenv: Multiline support

Created on 13 May 2017  路  12Comments  路  Source: motdotla/dotenv

I'm trying to load a multiline key but it includes the '=' character so it is dividing my key into multiple env vars.
screen shot 2017-05-13 at 12 27 49 pm

What can I do?

Most helpful comment

adding \n is tedious and ugly...

All 12 comments

Can you provide a complete example of what you're trying? Are you surrounding the value with double quotes (see our test value)?

Yeah, you can use double quotes and the newlines work properly.

CERT="-----BEGIN PUBLIC KEY-----\nabcdefg..."

There is one use case that the double quotes don't cover, and I'm curious if there is interest in accounting for this.

I embed JSON into some of my envs, specifically for arrays. This is easy to do with single quotes, or with double quotes and escaping the JSON-string double quotes inside the env. But neither of these work if I want to format my .env file a bit nicer; something like:

# Works
VALID_DOMAINS='["gmail.com","yahoo.com"]'

# Doesn't work (with single or double)
VALID_DOMAINS='[
  "gmail.com",
  "yahoo.com"
]'

# Parses Into
> process.env.VALID_DOMAINS === "["

Has this (admittedly very minor) use case been considered, and if so is there demand for a PR which investigates allowing it? I'd be happy to take a look.

@mhoc Any chance CERT="-----BEGIN PUBLIC KEY-----\nabcdefg..." can be replaced with

CERT="-----BEGIN PUBLIC KEY-----
            abcdefg..."

anytime soon? Having to convert a multiline cert into a single line value delimited by \n gets annoying quickly.

Closing this since it has been pretty quiet

I like this module but recently I needed to add PGP keys to the .env file and I had an enormous difficulty to do it by adding the whole key in line and adding \n to simulate a new line.

I am not sure about all the types of certificates and their declaration rules so I did not dare to send a "pull request" but, this modification solved for me.

    function parse (src) {
      var obj = {}    

      // certs
      var store_certs = [];
      var current_cert = '';
      var current_cert_key = '';
      var matching_cert = false;    

      // convert Buffers before splitting into lines and processing
      src.toString().split('\n').forEach(function (line) {
        // line length
        var line_len = line ? line.length : 0;    

        // matching "KEY' and 'VAL' in 'KEY=VAL'
        var keyValueArr = line.match(/^\s*([\w\.\-]+)\s*=\s*(.*)?\s*$/)
        // check if init cert declaration
        if ( /-----BEGIN/g.test(line) ) {
            matching_cert = true;
        }
        //
        if ( matching_cert ) {
            // check if end cert declaration
            if ( /-----END/g.test(line) && line_len > 0 && line.substring(line_len-5, line_len) === '-----' ) {
                current_cert += line + '\n';
                // strore
                store_certs.push({
                    key: current_cert_key,
                    value: current_cert
                });
                current_cert = '';
                current_cert_key = '';
                matching_cert = false;
            } else {
                if ( keyValueArr === null ) {
                    current_cert += line + '\n';
                } else {
                    current_cert_key = keyValueArr[1];
                    var value = keyValueArr[2] ? keyValueArr[2] : '';
                    current_cert += value + '\n';
                }
            }
        } else {
            // matched?
            if ( keyValueArr != null ) {
                var key = keyValueArr[1]
                // default undefined or missing values to empty string
                var value = keyValueArr[2] ? keyValueArr[2] : ''
                // expand newlines in quoted values
                var len = value ? value.length : 0
                if ( len > 0 && value.charAt(0) === '"' && value.charAt(len - 1) === '"' ) {
                    value = value.replace(/\\n/gm, '\n')
                }
                // remove any surrounding quotes and extra spaces
                value = value.replace(/(^['"]|['"]$)/g, '').trim()
                obj[key] = value
            }
        }
      });
      // if stored certs
      if ( store_certs.length > 0 ) {
          store_certs.forEach((item, i, array)=>{
              obj[item.key] = item.value;
          });
      }    

      return obj
    }

In me .env file e.g:

TOKEN_UNSUBSCRIBE=14wcn9tckujru2xirq8k38ulstgv7f9m1zg0te8gj9g
PRIV_KEY=-----BEGIN PGP PRIVATE KEY BLOCK-----
Version: OpenPGP.js v2.5.5
Comment: https://openpgpjs.org

xcaGBFlniGYBD/9vTm8Vbdlp72l67hX/3g8mGCe2zq1l+KIq83mwMRW0Y7Um
... [omit full certificate content]
mEGD32E1Fym2dllgE4zNW20OJXw+Fd3XgI/pDxg=
=WtrI
-----END PGP PRIVATE KEY BLOCK-----
PUB_KEY=-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: OpenPGP.js v2.5.5
Comment: https://openpgpjs.org

xsFNBFlniGYBD/9vTm8Vbdlp72l67hX/3g8mGCe2zq1l+KIq83mwMRW0Y7Um
... [omit full certificate content]
fD4V3deAj+kPGA==
=nm8/
-----END PGP PUBLIC KEY BLOCK-----

And I use it normally:

    console.log(process.env.TOKEN_UNSUBSCRIBE) // 14wcn9tckujru2xirq8k38ulstgv7f9m1zg0te8gj9g

    console.log(process.env.PRIV_KEY) // output complete private key

    console.log(process.env.PRIV_KEY) // output complete private key

@mhoc If it's a (possibly multiline) json, it won't be fun

single quotes maybe, ideally backticks

FOO=bar
SOME_KEY= ```
    {"foo": "bar", "qux": 1}
```
BIP_BOP='hello world'

Currently running into the same issue. The solution to add \n is ugly.

adding \n is tedious and ugly...

馃憤

Bump. I feel the behavior for the library should at least match similar behavior for Unix env variables. For certs, I can manage this perfectly as a normal env variable, but having to implement \n for dotenv is ugly, tedious, and not what I expected. Had to fumble a fair bit to notice it was an issue with dotenv itself.

I'd suggest implementing this format from the Ruby implementation:

```bash
PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----
...
HkVN9...
...
-----END DSA PRIVATE KEY-----"

Was this page helpful?
0 / 5 - 0 ratings

Related issues

marcusradell picture marcusradell  路  3Comments

Vandivier picture Vandivier  路  3Comments

shellscape picture shellscape  路  3Comments

samayo picture samayo  路  3Comments

datasmurfen picture datasmurfen  路  5Comments