Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

XMLHttpRequest (XHR) is broken in pre-request scripts in v4.5.1 #2232

Closed
dijitalmunky opened this issue Aug 5, 2016 · 35 comments
Closed

XMLHttpRequest (XHR) is broken in pre-request scripts in v4.5.1 #2232

dijitalmunky opened this issue Aug 5, 2016 · 35 comments
Assignees

Comments

@dijitalmunky
Copy link

In the latest version of Postman App on Mac OSX, the code new XMLHttpRequest() return a new empty object, not an actual XHR object as expected.

Version/App Information:

  1. Postman Version: 4.5.1
  2. App (Chrome app or Mac app): Mac App
  3. OS details: OS X El Capitan 10.11.6 (15G31)
  4. Is the Interceptor on and enabled in the app: No
  5. Did you encounter this recently, or has this bug always been there: After upgrading to 4.5.1 (From 4.4.2)
  6. Expected behaviour: XHR should work.

Steps to reproduce the problem:

  1. Create a request in Postman that you know works.
  2. Put the following script in the pre-request script tab:
var xhr = new XMLHttpRequest();
console.log("xhr:", xhr);
xhr.open('GET', 'http://jsonplaceholder.typicode.com/posts/1', false);
xhr.send();

if (xhr.status != 200) {
    console.error('Non-200 status code returned: ' + xhr.status, xhr);
    return;
}

var response = JSON.parse(xhr.responseText);

console.log('Response:', response);
  1. Open the devtools and execute the request, you should see the request succeed and a log item from the script that is similar to this (v4.4.2):
    image

In v4.5.1 I get the following instead (on the main Postman window:
image

and this as the output in the console window:
image

** NOTE ABOUT THE SCRIPT **
We use a similar script to this to make some requests to our auth server and set some Postman variables before the request executes so that the actual request will authenticate properly.

Unfortunately, we use a synchronous xhr call because there is no way we could find to make postman wait for all the async code in the pre-request script to complete before triggering the actual request.

Ideally, we'd like to be able to return a promise from the pre-request script that Postman could wait for before executing the main request. Alternatively, giving the pre-request script a callback function that could be invoked when the pre-request script is done would also be acceptable.

@shamasis
Copy link
Member

shamasis commented Aug 6, 2016

Postman scripts were not supposed to make requests. The request itself is there to do that. Since we now run the scripts within underlying NodeJS scope, XHR is not longer valid.

Instead of using an XHR call to fetch variables, can you add an actual request to fetch the variables of possible?

@dijitalmunky
Copy link
Author

dijitalmunky commented Aug 6, 2016

I could, however, the tokens that we get are very short lived (60 seconds), so unless there is an automatic way to chain requests together, the pre-request script is ideal. Here is actually what we do in the pre-request script currently:

  1. get the current value of the token
  2. check the expiry date of the token
  3. if the token is still good, return from the script
  4. if, not, request another token and set the variables

To do this manually with multiple requests is very tedious and error prone and leaves a less than desirable user experience. If Postman is now running under nodeJS, then is there anything stopping us from using node's 'http' module?

** UPDATE: **
Just tried it and it looks like require is disabled in the context of the pre-request scripts, so I think I just answered my own question...hehe.

@dijitalmunky
Copy link
Author

dijitalmunky commented Aug 6, 2016

Hrm...just had a look at the Authorization section again (we originally tried it and while it worked, it had some drawbacks). However there are still few items that make it less than desirable for us:

  1. You seem to need to manually get a new token once the current one expires (this means we need to do this often because of our short expiry). It would be nice if once this is set up, it could simply track your token and when it expires, POSTMAN just gets a new one and uses that. Is there a way to do this?
  2. You have to manually choose which token you want to use. We have environment variables all setup to make the requests to the appropriate server (and these are used in the OAuth 2.0 configuration in postman), so we'd just like to setup the OAuth authentication and have it automatically just be used when we hit the send button for the request.

It was actually these two reasons that led us to develop the pre-request script above that broke.

@shamasis
Copy link
Member

shamasis commented Aug 8, 2016

Okay. Did you have a look at postman.setNextRequest? Allows you to jump to one request from another. What if you set auth request and jump to that after test and return to where you want?

If that helps, we discuss more.

@dijitalmunky
Copy link
Author

I did not know about setNextRequest. I am not sure I am following what you are saying with regards to What if you set auth request and jump to that after test and return to where you want?. It sounds like you are asking if we can trigger the auth request after our main request? Is this correct? Or is there a clarification you can make?

@shamasis
Copy link
Member

Sorry for being so vague in my last reply. The feature I'm referring to is - https://www.getpostman.com/docs/workflows

@dijitalmunky
Copy link
Author

Hrm, that works but it is still cumbersome. Perhaps I should try to explain a little more about how we use Postman.

First we are NOT using the whole testing part of it at this time. We are using it more as a developer tool at this time. Here is a typical flow.

  1. Developer opens our API on his/her machine.
  2. Developer makes some changes to one of the endpoints or adds a new endpoint.
  3. Developer opens Postman. They tweak the request (or make a new one) to quickly test their change.
  4. iterate as necessary.

All of our requests share the same method of getting a token. Therefore, the suggestion to use test scripts and the setNextRequest call is cumbersome, because in this workflow, we have to go into the request for the token and change the next request constantly.

We also use postman to check on individual API calls that have failed for our clients or ourselves. In this case we use a very similar flow as above, simply because they are one off requests.

As mentioned above, the Authorization tab is 90% of the way there for us, so we'll probably use that. However, if feature requests could be made for the following functionality, I believe it would make POSTMAN much easier to use:

  • Have the authorization sections be shareable between requests (it is not a deal breaker to not have this, as we typically copy an existing request and edit it for new endpoints)
  • Have the OAUTH 2.0 Authorization section understand JWTs and add an option that the authorization section can automatically get a new token if the currently used one has expired. This is the real deal breaker for us with the Authorization module right now, because our tokens are so short lived, we constantly need to go back in manually and switch the tokens.

@a85
Copy link
Contributor

a85 commented Aug 17, 2016

@dijitalmunky That's super helpful. Let us think about this use case more and figure out the best solution.

@prdonahue
Copy link

We have the exact same issue as the OP. Because Postman does not have an easy way to make a POST with credentials and extract a bearer token (as part of the built-in authorization schemes) we are forced to add a pre-request script to all of our calls:

eval(postman.getEnvironmentVariable("LOGIN_DEFAULT_ADMIN"));

And because there is not a reusable library of our functions, we've jammed that function into an environment variable that does the following:

var login_uri = 'http://' + postman.getEnvironmentVariable('BASE_URI') + '/' + postman.getEnvironmentVariable('LOGIN_PATH');
var post_data = { 'username': postman.getEnvironmentVariable('ADMIN_USER'), 'password': postman.getEnvironmentVariable('ADMIN_PASS') };

var xhr = new XMLHttpRequest();
xhr.open('POST', login_uri, false);
xhr.setRequestHeader('content-type', 'application/json');
xhr.send(JSON.stringify(post_data));
resp = JSON.parse(xhr.response);
postman.setEnvironmentVariable('bearer_token', resp.token);

This is an incredibly common way of auth'ing, so unless I'm missing something in a new version—have been afraid to upgrade because xhr.open is now broken—then we need a less cumbersome solution than presented in the replies to OP.

Thanks!

@prdonahue
Copy link

Basically, I think improving/generalizing the authorization functionality will solve 90% of cases—but I still don't see why we can't make calls from the pre-request script or the post-run tests? There are all sorts of reasons one would want to do this. Is there really no way anymore?

@a85
Copy link
Contributor

a85 commented Sep 7, 2016

@prdonahue We are thinking of doing both: custom auth plus the ability to send requests from pre-requests/test scripts. Will post an update here soon.

@norfanos
Copy link

Any word? I've got near identical concerns. Checking/Getting/Setting a token. Thanks.

@choonkeat
Copy link

I have a POST /login request that logs in successfully against a server endpoint that returns a JWT token. In that request, under Tests tab, I have a simple test

var jsonData = JSON.parse(responseBody);
tests["access_token"] = jsonData.access_token !== "";

postman.setEnvironmentVariable("JWT", jsonData.access_token);

In all other requests that require JWT, I setup the Headers tab to be

key=Authorization
value=Bearer {{JWT}}

I just have to click Send on the Login request once (which sets the environment variable), and the rest of the authenticated API calls will work (which uses the environment variable in their Authorization: Bearer {{JWT}} header.

@bobhigs
Copy link

bobhigs commented Mar 8, 2017

Has there been any progress on this? I just updated to the latest version and XMLHttpRequest is still broken. There are a lot of use cases for being able to execute one request before another and postman.setNextRequest does not cover this.

Something like postman.executeRequest(requestName) would solve this issue.

@lloydjatkinson
Copy link

Yep still broken for me.

@dijitalmunky
Copy link
Author

Agreed, an update on progress/decisions would be nice. While more automation around the flows defined by oauth2.0/oidc would be nice and a definite timesaver, we have gotten used to the auth helpers (https://www.getpostman.com/docs/helpers) and needing to constantly get new and delete expired tokens.

@lloydjatkinson
Copy link

I've started looking at alternatives, I can only assume XMLHttpRequest was broken deliberately so they can push "extra" features for some kind of pro/subscription model.

@a85
Copy link
Contributor

a85 commented Apr 9, 2017

@lloydjatkinson No. We did not want to build another set of meta-tools when people start sending API requests within scripts. We have a better solution now through the new pm.api that is planned for release soon. We'll update the thread when it is out.

@blakebrauer
Copy link

@a85 Any update on this? I too am looking for a way to get and set a token before a request. "setNextRequest" would be sufficient except I need something that works outside of a collection run.

@bjammin
Copy link

bjammin commented Jul 11, 2017

This is very frustrating. I have a method similar to the above (put a function into a global variable and call it from all of our scripts pre-request script using eval). It works fine in the chrome app.

Some of our developers are using the standalone postman app though (which I believe is the supported standard moving forward) ... and it doesn't work there (XMLHttpRequest is not defined).

setNextRequest is useless for this workflow, as we want to call the actual request we want and then to have it call the authentication request.

The best way I can see to get this working (apart from allowing some kind of http request access) would be to be able to call another request by name from the pre-request script (or some other method).

eg.
postman.callRequest('GetToken');

Is there a solution for this forthcoming?

@gukoff
Copy link

gukoff commented Jul 28, 2017

Same here.

I use Postman for Mac. It doesn't have XMLHttpRequest in the tests' namespace: ReferenceError: XMLHttpRequest is not defined.

I want to collect the urls from the API response and verify all of them are accessible. That said, requests to them return HTTP 200. And I can't do such a basic test.

@festus3001
Copy link

Same here.

Perhaps it's just in the backlog and not a lock-in strategy? Please add XMLHttpRequest back in.

@jvkaam
Copy link

jvkaam commented Aug 9, 2017

+1

@babaorum
Copy link

Hi, I am having the same problem.

One of my suprises was that there was not real custom authorization part.
Maybe we should dig this way to find a good solution.
This would allow us, to use whatever way we want. For example I would be ok to just be able to give a script which would return the data. Or an url which would get the data by himself and return it. But I won't change for Oauth2 just for this.

@kunagpal
Copy link
Member

kunagpal commented Sep 22, 2017

This is now possible in Postman v5.2.0 and above, with pm.sendRequest. See https://www.getpostman.com/docs/postman/scripts/postman_sandbox_api_reference#pmsendrequest for a working example.

@aaiezza
Copy link

aaiezza commented Jan 15, 2018

I appreciate that pm.sendRequest is a thing; however, when I try to use it, I get an error:

image

Thoughts?

@kunagpal
Copy link
Member

kunagpal commented Jan 16, 2018

@aaiezza Are you on the Chrome app? This feature is exclusive to native apps.

@aaiezza
Copy link

aaiezza commented Jan 16, 2018

I think I am. Where can I download the native app?

Correction

Actually , when I start Postman on macos, I see a warning that Chrome apps are being deprecated and to download the free native app for continued support and better performance.

@kunagpal
Copy link
Member

Yes, you can download the native app from: https://getpostman.com/apps

@aaiezza
Copy link

aaiezza commented Jan 16, 2018

@kunagpal, gotcha. So I actually did use that link to install Postman. I download, unzip, and drop the .app file into Applications and run it.
However, it seems to be "connected" to Chrome still somehow.

For instance, I still don't see that pm functionality working in my pre-scripts.
And ⌘+Tab does not switch between Postman & Chrome, even though the Postman app has an icon in the Application Switcher. Switching between them, if either one is already a focused window, requires ⌘+~.

Thoughts?

@sivcan
Copy link
Member

sivcan commented Jan 16, 2018

Hi @aaiezza,
If you do a spotlight search (⌘+Space) you can see the two apps like so:
screen shot 2018-01-16 at 11 05 11 pm

The one that's the native app will have 'Applications' written besides it.
The chrome app has 'Chrome Apps' written besides it.
Can you confirm that you're running the 'Applications' one ?

And also once you launch the native app,
You'll see the following menu also :
screen shot 2018-01-16 at 11 08 56 pm

  1. Can you confirm these two things ?
  2. Also, when you launch the Postman chrome app, it'll automatically launch 'Google Chrome' with it. To test, you can quit google chrome and launch postman. If Google chrome is also launched with it (You might not see a window of Google Chrome) but you'll see the white dot under it in the dock.

screen shot 2018-01-16 at 11 12 17 pm

Whereas this won't happen for the native app.

@aaiezza
Copy link

aaiezza commented Jan 16, 2018

Hi @sivcan,

I actually do not see a Chrome App version at all. I do not think I have any chrome apps installed.
In Spotlight, it says Postman is an application.
When running Postman, I also have that menu that you have shown here.

I did run your test though!
I quit Google Chrome (entirely) and Postman.
When I was sure they were both terminated, I started ONLY Postman.
Postman started. Also, while no Chrome window appeared, Chrome DID bounce and start!
I'm tempted, but reluctant to try uninstalling Google Chrome all together, and then try running Postman since it should work standalone.

@aaiezza
Copy link

aaiezza commented Jan 16, 2018

Eureka!
I have found Postman Canary!
Very strange... But this one seems to work.
Thank you all!

Except now my issue is that environment variables are no longer resolved in the Pre-request scripts.
Any ideas?

@sivcan
Copy link
Member

sivcan commented Jan 17, 2018

@aaiezza - I can confirm that the environment variables are being resolved on Postman Canary.
I wrote a simple request and did set the environment variable using the pre-request script.

screen shot 2018-01-17 at 1 24 21 pm

You can see the response below that the url is being correctly hit with the variables resolved.

If not this, then is it something else that you're trying to do ?
Can you share the script with me ?

Thanks

@aaiezza
Copy link

aaiezza commented Jan 17, 2018

@sivcan, Forgive me for being unclear.
I mean that in the pre-request script itself, there was variable replacement happening. In PostmanCanary, there is not.

pmexample
pmexampleconsole

Variables in my request URL(path and params), headers, and body are all getting replaced successfully.
The Chrome app version apparently also allowed it in the pre-request scripts.

PostmanCanary is however in an "early adopter" stage; maybe this is an issue for that product instead of here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
No open projects
Sandbox/Runtime
Suggestions
Development

No branches or pull requests