bruno icon indicating copy to clipboard operation
bruno copied to clipboard

Regression: Environment Variables Values Not Working Since v1.18.0

Open Peperomain opened this issue 1 year ago • 1 comments

I have checked the following:

  • [X] I use the newest version of bruno.
  • [X] I've searched existing issues and found nothing related to my issue.

Describe the bug

Since updating to version 1.18.0, environment variables used within the values of other environment variables no longer work as expected. This feature was available and worked correctly since version 1.17.0.

Setup

Let's take a GET request at https://catfact.ninja/fact that retrieves random cat facts via text message every day : image You can see that the URL is a variable, which comes from the environment variables as shown here : image As you can see, url is also made up of another environment variable Cat.

.bru file to reproduce the bug

environements/Local.bru

vars {
  Cat: https://catfact.ninja
  url: {{Cat}}/fact
}

cat.bru

meta {
  name: cat
  type: http
  seq: 3
}

get {
  url: {{url}}
  body: none
  auth: none
}

Screenshots/Live demo link

Versions before v1.17.0

I would get an error : image image

Version v1.17.0

I would get a 200 OK with the wanted response : image image

Version 1.18.0

But since the 1.18.0 update, I get the same error as I did before version 1.17.0: image image

Peperomain avatar May 23 '24 11:05 Peperomain

@Peperomain

The fix in v1.17.0 was incidental and not a proper one.

For example: Screenshot 2024-05-23 at 6:28:31 PM Screenshot 2024-05-23 at 6:28:44 PM

The above scenario doesn't work in v1.17.0 either.

To properly solve this, multi-level interpolation needs to be done.

I do plan on working on this if time permits and based on my other task priorities.

This issue can be overcome through scripting. Do let me know if you need any help with it.

lohxt1 avatar May 23 '24 13:05 lohxt1

Hi @lohxt1,

Thanks a lot for the quick response and for explaining the situation. I really appreciate it!

About the scripting workaround you mentioned, could you share some tips or examples on how to do this? It'd be super helpful to understand how to handle environment variable interpolation with scripts.

Thanks again for your help!

Cheers, Peperomain

Peperomain avatar May 26 '24 19:05 Peperomain

Hey @Peperomain

sure, here's a simple script that'l create a equivalent collection var with the interpolated env var value.

const patternRegex = /\{\{([^}]+)\}\}/g;

const vars = bru.envVariables;

console.log("before:");
console.log(vars);
console.log("-----------------");

const interpolate = (str) => {
  return str && str.replaceAll(patternRegex, (match, placeholder) => {
    const replacement = vars[placeholder];
    return replacement !== undefined
      ? patternRegex.test(replacement)
        ? interpolate(replacement)
        : replacement
      : match;
  });
};

let interpolatedVars = {};
Object.entries(vars).map(([key, value]) => {
  interpolatedVars[key] = interpolate(value);
  bru.setVar(key, interpolate(value));
});

console.log("after:");
console.log(interpolatedVars);
console.log("-----------------");
vars {
  host: http://example.com
  path: foo
  urlWithPath: {{url}}{{path}}/bar
  url: https://example.com/
  bigUrl: {{urlWithPath}}/baz
}

You can add this in the collection level pre-request script. And since the collection variables hold higher precedence over env vars, interpolated values will be used.

https://github.com/usebruno/bruno/assets/159901171/a781c6ac-1b81-413d-980d-ddb38ab5001b

lohxt1 avatar May 27 '24 08:05 lohxt1

The above script does not place the value of a a process.env.* variable into Bruno environment variables. Version 1.17.0 does it, but only without the above script.

Given, e.g.:

Name Value
bearer_token {{client_id}}:{{client_secret}}
client_id {{process.env.STG_ID}}
client_secret {{process.env.STG_SECRET}}

where I've defined STG_ID and STG_SECRET in my dotenv file

and using {{bearer_token}} for Auth at the Collection level: Screenshot 2024-05-31 at 00 27 43

Before the script in v1.18.0+, Bruno sends this as Auth:

...
> Authorization: Bearer {{client_id}}:{{client_secret}}
...

After the script in v1.17.0+, Bruno sends this as Auth:

...
> Authorization: Bearer {{process.env.STG_ID}}:{{process.env.STG_SECRET}}
...

Since this sets the collection vars, the quickest way to undo everything this script does is, unfortunately, to restart Bruno.

Since we sometimes need a temporary Bearer token and other times can use a client ID and secret, it's far easier for us to manage our authorization in our secrets file (as opposed to copy-pasting every time we switch environments).

What's the "right" way to incorporate process.env.* variables into your script?

How can I add my vote to (or help with) getting a "proper" fix in -- one that doesn't need an extra pre-script that sets the collection vars?

coactive-jeffrey avatar May 31 '24 07:05 coactive-jeffrey

From the example above, using v1.17.0+ with the script:

Screenshot 2024-05-31 at 00 56 15 Screenshot 2024-05-31 at 00 56 22 Screenshot 2024-05-31 at 00 56 26

But with v1.17.0 without the script, it grabs the {{process.env.JEFF}} value buzz, but (as you pointed out) cannot get the {{path}} value:

Screenshot 2024-05-31 at 00 58 32

coactive-jeffrey avatar May 31 '24 08:05 coactive-jeffrey

you can modify the script to include process env vars like below

pre-request script

const patternRegex = /\{\{([^}]+)\}\}/g;

const processEnvVars = Object.entries(bru.processEnvVars)?.reduce((acc, [key, value])=>{
  acc[`process.env.${key}`] = value;
  return acc;
}, {})

const vars = {
  ...bru.envVariables, 
  ...processEnvVars
};

console.log("before:");
console.log(vars);
console.log("-----------------");

const interpolate = (str) => {
  return str && str.replaceAll(patternRegex, (match, placeholder) => {
    const replacement = vars[placeholder];
    return replacement !== undefined
      ? patternRegex.test(replacement)
        ? interpolate(replacement)
        : replacement
      : match;
  });
};

let interpolatedVarKeys = []
let interpolatedVars = {};
Object.entries(vars).map(([key, value]) => {
  interpolatedVars[key] = interpolate(value);
  bru.setVar(key, interpolate(value));
  interpolatedVarKeys.push(key);
});

bru.setVar('temp', JSON.stringify(interpolatedVarKeys));

console.log("after:");
console.log(interpolatedVars);
console.log("-----------------");

and to clear/null the temporarily created collection vars

add the below code to the post-response script

post-response script

const interpolatedVarKeys =  [...JSON.parse(bru.getVar('temp')), 'temp'];
interpolatedVarKeys.forEach(key=>bru.setVar(key, null));

https://github.com/usebruno/bruno/assets/25679466/cb6c8997-9d4a-412d-af98-3b913b8c492b

this is in v1.18.0

lohxt1 avatar May 31 '24 08:05 lohxt1

Environment variables set in pre-requests scripts using bru.setVar are not shown in Collection variables tab at all. Thus, they are also impossible to use in Auth tab, e.g. Bearer token. I can read the variable after I set it in the pre-request script itself, but I cannot access it in either Auth or Variables tab.

Bruno in 1.18.1

Screenshot 2024-06-04 at 17 45 26 Screenshot 2024-06-04 at 17 46 57 Screenshot 2024-06-04 at 17 46 24

technodrome avatar Jun 04 '24 15:06 technodrome

Just noticed this post here as I was preparing to report another bug post on this. This is definitely a problem in our enterprise. We will all now have to downgrade to v17.0 to have our scripts working again.

image

image

image

The extra scripting seems to work, but I cannot ask all of our enterprise teams to do this. We will wait for the next fixed version before we upgrade from v1.17.0.

james-yin avatar Jun 07 '24 19:06 james-yin

@technodrome you could add your script in the collection pre-request script and use the token in your requests

i have attached a sample bruno collection json this is in v1.18.0

token_test.json

lohxt1 avatar Jun 14 '24 10:06 lohxt1

@james-yin could you share a sample bru file or a collection showing what you are doing with the url value in the pre-request script, it would help us understand your use-case better

lohxt1 avatar Jun 14 '24 10:06 lohxt1

@lohxt1

I'm attaching my test collection script along with 2 screenshots between v1.17 & v1.19. The issue is how the environment variable is evaluated between 17 and 19. In 17, during 'Pre' script, the env variable was evaluated correct. But in 19, it does not evaluate correctly as you can see from my screenshots.

v1.17 - evaluates env var correctly: image

v1.19 - evaluates env var incorrectly: image

Here's my simple Bruno collection: bruno-test.zip

james-yin avatar Jun 14 '24 15:06 james-yin

Fixed in 1.20.0

Peperomain avatar Jul 03 '24 15:07 Peperomain

this issue is not fixed in v20. if you execute the collection i posted, the problem still exists. i've just created a new bug issue.

james-yin avatar Jul 03 '24 17:07 james-yin

this issue is not fixed in v20. if you execute the collection i posted, the problem still exists. i've just created a new bug issue.

Thank you for your feedback, James. In my use case, the issue seems to be resolved in version 20, which is why I closed the issue. It's concerning that it still persists for you. Hopefully, the new bug issue you've created will be resolved soon.

Peperomain avatar Jul 03 '24 18:07 Peperomain

@technodrome you could add your script in the collection pre-request script and use the token in your requests

i have attached a sample bruno collection json this is in v1.18.0

token_test.json

Does not work with 1.20.1. On top of that, declaring something as collection var just to make it work (if it actually did) is not the right approach IMO. Even when I move the script to collection pre-request script section, I see my token using getVar in the dev console but Collection variables do not show this programmatically defined variable and it is also unavailable (red font) in the auth bearer token input field using {{auth_token}}. Broken.

I'll have to stick with Insomnia which even has nice built-in dialogue for these response variables. I do not mind defining things programmatically but it seems completely broken to me.

technodrome avatar Jul 06 '24 21:07 technodrome