Giter VIP home page Giter VIP logo

Comments (8)

cdimascio avatar cdimascio commented on May 28, 2024 1

Thanks for the details. This is helpful. Will have a look

from dotenv-kotlin.

david-arteaga avatar david-arteaga commented on May 28, 2024 1

Yeah Base64 definitely gets the job done. Did not occur to me at the moment so ended up putting something like __NEWLINE__ in the .env file and then replacing it when reading the values in the Java code.
Thanks for taking the time to go over the Java behavior! I do agree with you that it should stay the same as what System.getenv does.
Maybe we could add something to the README there is a reference to the issue in the future. Coming in, I thought the newlines would just work and took me well over an hour to realize that was the issue I had, given the use case I had.

from dotenv-kotlin.

cdimascio avatar cdimascio commented on May 28, 2024

@david-arteaga thanks for the ticket

I created a quick simple test to try and recreate your issue

Here is my .env file

MULTI_LINE=hello\nworld

Here is a quick Java test (included only the relevant bits)

   ...
    private val envVars = mapOf(
        "MULTI_LINE" to "hello\\nworld"
    )
   ...

    @test
    fun multiLine() {
        val dotenv = Dotenv.configure()
            .ignoreIfMalformed()
            .load()

        assertEquals(dotenv["MULTI_LINE"]!!, envVars["MULTI_LINE"]!!)
    }

The above test passes.

Can you provide the .env file you are using and what you expect to see in Java

Thanks

from dotenv-kotlin.

david-arteaga avatar david-arteaga commented on May 28, 2024

Ok so I played around with some examples and I think I got to the issue.

This is my .env file:

MULTILINE=1\n2

This is the code I am running

public static void main(String[] args) {
  String multilineString = "1\n2";

  Dotenv d = Dotenv.load();
  String multilineFromDotEnv = d.get("MULTILINE");

  System.out.println("Characters from multiline");
  printChars(multilineString);
  System.out.println("\n\nCharacters from dotenv");
  printChars(multilineFromDotEnv);

  System.out.println("\n\nPrinted string with multiline");
  System.out.println(multilineString);
  System.out.println("Printed string from dotenv");
  System.out.println(multilineFromDotEnv);

  System.out.println("\n\nAre they equal? : " + multilineString.equals(multilineFromDotEnv));
}

private static void printChars(String all) {
  all.chars().forEach(System.out::println);
}

This is the output I get:

Characters from multiline
49
10
50


Characters from dotenv
49
92
110
50


Printed string with multiline
1
2
Printed string from dotenv
1\n2


Are they equal? : false

So as you can see in the character list from dotenv, the characters get interpreted literally, as a \+ n character.

I would expect for there to be a way to actually have a real multiline string from dotenv.

I ran into this problem trying to use a .pem certificate in the .env file, and the library I was using rightfully complained saying the certificate was incorrect.

I can imagine there are many other use cases for this, but this is the one I found.

I want the string that is loaded from dotenv to actually have the newline character in the string, not to have the \+ ncharacters.

Is there any way to do this with the library?
What I did in the end was just to put an arbitrary string where there should be newlines in the .env file and then replace them in java code.

from dotenv-kotlin.

cdimascio avatar cdimascio commented on May 28, 2024

@david-arteaga

I ran a few more tests. Ultimately, Java's System.getenv(...) and java-dotenv's dotenv.get(...) behave the same way for multi-line EVs. Given that this is the case, the current behavior should remain. I don't think dotenv should diverge from Java's behavior.

Here is the test. It's essentially an extension of yours

package tests;

import io.github.cdimascio.dotenv.Dotenv;

import java.util.ArrayList;
import java.util.List;

public class Test
{
    public static void main(String[] args) {
        String multilineString = "1\n2";

        Dotenv d = Dotenv.configure().ignoreIfMalformed().load();
        String multilineFromDotEnv = d.get("MULTILINE");
        String multilineFromSytemEnv = System.getenv("MULTILINE");

        System.out.println("Characters from");
        System.out.println(" - multiline: " + collectChars(multilineString));
        System.out.println(" - dotenv   : " + collectChars(multilineFromDotEnv));
        System.out.println(" - System   : " + collectChars(multilineFromSytemEnv));

        System.out.println();
        System.out.println("String from");
        System.out.println(" - multiline: " + multilineString);
        System.out.println(" - dotenv   : " + multilineFromDotEnv);
        System.out.println(" - System   : " + multilineFromSytemEnv);

        System.out.println();
        System.out.println("Does System.getenv(...) equal dotenv.get(...): " + multilineFromSytemEnv.equals(multilineFromDotEnv));

        System.out.println("Does System.getenv equal multiline String?   : " + multilineString.equals(multilineFromSytemEnv));
        System.out.println("Does dotenv.get equal multiline String?      : " + multilineString.equals(multilineFromSytemEnv));
    }

    private static List<Integer> collectChars(String all) {
        return all.chars().collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
    }
}

from dotenv-kotlin.

cdimascio avatar cdimascio commented on May 28, 2024

All in all, this still begs the question, how do you solve your original issue.

Here's a suggestion. Base 64 encode the multi-line value in the EV, and decode it after its read in.
Here is an example, you'll notice that the bae64 encoding will preserve the newlines and both Java system and dotenv produce the same and desired result

# EVs 
MULTILINE=1\n2
# base 64 encoded version of string above
B64_MULTI_LINE=MQoy
package tests;

import io.github.cdimascio.dotenv.Dotenv;

import java.util.ArrayList;
import java.util.Base64;
import java.util.List;

public class Test
{
    public static void main(String[] args) {
        String multilineString = "1\n2";
        runWith("MULTILINE", "1\n2");
        System.out.println("=================");

        String encodedString = Base64.getEncoder().encodeToString(multilineString.getBytes());

        runWith("B64_MULTI_LINE", encodedString);

        byte[] decodedBytes = Base64.getDecoder().decode(encodedString);
        System.out.println(new String(decodedBytes));
    }

    public static void runWith(String ev, String multilineString) {
        Dotenv d = Dotenv.configure().ignoreIfMalformed().load();
        String multilineFromDotEnv = d.get(ev);
        String multilineFromSytemEnv = System.getenv(ev);

        System.out.println("Characters from");
        System.out.println(" - multiline: " + collectChars(multilineString));
        System.out.println(" - dotenv   : " + collectChars(multilineFromDotEnv));
        System.out.println(" - System   : " + collectChars(multilineFromSytemEnv));

        System.out.println();
        System.out.println("String from");
        System.out.println(" - multiline: " + multilineString);
        System.out.println(" - dotenv   : " + multilineFromDotEnv);
        System.out.println(" - System   : " + multilineFromSytemEnv);

        System.out.println();
        System.out.println("Does System.getenv(...) equal dotenv.get(...): " + multilineFromSytemEnv.equals(multilineFromDotEnv));

        System.out.println("Does System.getenv equal multiline String?   : " + multilineString.equals(multilineFromSytemEnv));
        System.out.println("Does dotenv.get equal multiline String?      : " + multilineString.equals(multilineFromSytemEnv));

        String encodedString = Base64.getEncoder().encodeToString(multilineString.getBytes());
    }

    private static List<Integer> collectChars(String all) {
        return all.chars().collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
    }
}

Hope this helps

from dotenv-kotlin.

cdimascio avatar cdimascio commented on May 28, 2024

Done. I’ve added a note in the FAQ section.

from dotenv-kotlin.

david-arteaga avatar david-arteaga commented on May 28, 2024

Just for reference the FAQ section is here

from dotenv-kotlin.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.