I know I'm able to log a single response cookie using Postman, but is it possible to log ALL the response cookies in one go?
I'm trying to troubleshoot a test and would like to know what cookies are coming back, and I can't seem to get this solution to work:
const jar = pm.cookies.jar();
jar.clear(env, function (error) {
jar.getAll(env, function (error, cookies) {
console.log("cookies: " + cookies);
});
});
In the console "cookies" just remains undefined, and that's after adding the above code to the 'Tests' tab...
Thanks.
I resolved this issue by replacing the following line
const env = "integration-api.yyyy.xxx.xxxx.net";
with the full endpoint URL:
const env = "integration-api.yyyy.xxx.xxxx.net/api/v1/etc/etc";
Full code now looks like this:
const env = "integration-api.yyyy.xxx.xxxx.net/api/v1/etc/etc";
const jar = pm.cookies.jar();
jar.getAll(env, function (error, cookies) {
console.log("cookies: " + cookies);
});
Thanks to #DannyDainton for the pointers.
Related
I have a Next.js application where authentication is set up with the Auth0 Next.js SDK.
Currently the AUTH0_CLIENT_SECRET is being set as an environment variable when deploying.
I would like to use Google Cloud Secret Manager to get the AUTH0_CLIENT_SECRET during runtime and set it using the initAuth0 method.
I'm following this example: https://github.com/auth0/nextjs-auth0/blob/main/EXAMPLES.md#create-your-own-instance-of-the-sdk
But I can't figure out how I can await the response from secret manager when I need to have the secret ready for calling the method initAuth0({clientSecret...}) and I need that in place to setup the auth end points with auth0.handleAuth().
This is my attempt: /pages/api/auth/[...auth].ts
import { initAuth0 } from "#auth0/nextjs-auth0";
const asyncHandleAuth = async () => {
const clientSecret = await getSecret("AUTH0_CLIENT_SECRET");
const auth0 = initAuth0({
clientSecret // The rest of the config is set with environment variables
});
return auth0.handleAuth();
};
export default asyncHandleAuth();
After some hair pulling I found the problem. Next.js expects the export default function to be of type NextApiHandler but I was returning Promise<NextApiHandler>.
I solved it by wrapping it in another function that takes the request and response arguments and use them to call handleAuth before returning it.
This worked for me:
const asyncHandleAuth =
() => async (req: NextApiRequest, res: NextApiResponse) => {
const clientSecret = await getSecret("AUTH0_CLIENT_SECRET");
const auth0 = initAuth0({
clientSecret, // The rest of the config is set with environment variables
});
return auth0.handleAuth()(req, res);
};
export default asyncHandleAuth();
In the code you posted in your answer:
const clientSecret = await getSecret("AUTH0_CLIENT_SECRET");
you are already waiting until the secret is returned: your code will suspend on that line until getSecret ends. As a consequence, the secret should be ready when using the initAuth0 function.
Perhaps, and according to your comments, the problem could be motivated by your export. You are exporting the asyncHandleAuth function like this:
export default asyncHandleAuth();
But I think it should be instead:
export default asyncHandleAuth;
Your answer makes perfect sense: the actual problem is that you need to provide the appropriate arguments, the request and response representations, to your handler function to perform the actual invocation. But please, be aware that the proposed export default still is valid, in your code you are executing a function that returns the thing that is being exported. Probably you could simplify it like this:
import { initAuth0 } from "#auth0/nextjs-auth0";
const asyncHandleAuth = async (req: NextApiRequest, res: NextApiResponse) => {
const clientSecret = await getSecret("AUTH0_CLIENT_SECRET");
const auth0 = initAuth0({
clientSecret // The rest of the config is set with environment variables
});
return auth0.handleAuth()(req, res);
};
export default asyncHandleAuth;
Note that there is no need for the first arrow function.
I need to make requests to an API that accepts authentication tokens and I want to be able to use a dynamically generated token by running cmd.exe /c GenerateToken.bat instead of having to run my program and then manually paste the value in Postman every time.
I imagine something that looks like this:
How can I set the value of a HTTP header to contain the stdout output of a program or a batch file?
Short answer is, you can't. This is deliberate, both pre-request and test scripts (the only way, other than a collection runner, to make your environment dynamic) run in the postman sandbox, which has limited functionality.
More information of what is available is in the postman-sandbox Github repository page and in postman docs (scroll to the bottom to see what libraries you can import)
You do have a few options, as described in comments - postman allows sending requests and parsing the response in scripts, so you can automate this way. You do need a server to handle the requests and execute your script (simplest option is probably a small server suporting CGI - I won't detail it here as I feel it's too big of a scope for this answer. Other options are also available, such as a small PHP or Node server)
Once you do have a server, the pre-request script is very simple:
const requestOptions = {
url: `your_server_endpoint`,
method: 'GET'
}
pm.sendRequest(requestOptions, function (err, res) {
if (err) {
throw new Error(err);
} else if (res.code != 200) {
throw new Error(`Non-200 response when fetching token: ${res.code} ${res.status}`);
} else {
var token = res.text();
pm.environment.set("my_token", token);
}
});
You can then set the header as {{my_token}} in the "Headers" tab, and it will be updated once the script runs.
You can do something similar to this from Pre-request Scripts at the collection level.
This is available in postman for 9 different authorization and authentication methods.
this is a sample code taken from this article, that show how to do this in Pre-request Scripts for OAuth2
// Refresh the OAuth token if necessary
var tokenDate = new Date(2010,1,1);
var tokenTimestamp = pm.environment.get("OAuth_Timestamp");
if(tokenTimestamp){
tokenDate = Date.parse(tokenTimestamp);
}
var expiresInTime = pm.environment.get("ExpiresInTime");
if(!expiresInTime){
expiresInTime = 300000; // Set default expiration time to 5 minutes
}
if((new Date() - tokenDate) >= expiresInTime)
{
pm.sendRequest({
url: pm.variables.get("Auth_Url"),
method: 'POST',
header: {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': pm.variables.get("Basic_Auth")
}
}, function (err, res) {
pm.environment.set("OAuth_Token", res.json().access_token);
pm.environment.set("OAuth_Timestamp", new Date());
// Set the ExpiresInTime variable to the time given in the response if it exists
if(res.json().expires_in){
expiresInTime = res.json().expires_in * 1000;
}
pm.environment.set("ExpiresInTime", expiresInTime);
});
}
I have a SSR Nuxt app. There is a middleware in the page code.
I dont know is I can use js-cookies library in that middleware and if it will work as I expected. I need to get and set up the cookie in browser and also get the cookie value on the server. All this steps in the middleware.
I mean
check if cookie is set via Cookies.get(key)
if not then set up the cookie via Cookies.set(key, value)
redirect to the server where I want to get this cookie value
Code should look like
async middleware(context) {
const token = context.route.query.token;
if (!token) {
const cookieToken = Cookies.get('cookieToken');
if( !cookieToken ) {
Cookies.set('cookieTokne', nanoId());
}
const result = await context.$api.campaignNewShare.createNewShare();
context.redirect({'name': 'campaigns-new', 'query': {token: result.data.token}});
}
},
Am I able to get cookie after the set on the server and can I get it in the browser after the redirect? I need to ensure both set and get in this middleware at once.
Use nuxt universal cookies and register on your modules, this way you can access the module everywhere on your nuxt app.
Using your code as example:
async middleware(context) {
const token = context.route.query.token;
if (!token) {
const cookieToken = context.$cookies.get('cookieToken');
if( !cookieToken ) {
context.$cookies.set('cookieToken', nanoId());
}
const result = await context.$api.campaignNewShare.createNewShare();
context.redirect({'name': 'campaigns-new', 'query': {token: result.data.token}});
}
},
How can I output a clickable URL in the Postman Console (native app) from within a test script?
Like the "https://go.pstmn.io/postman-jobs" when you start the Postman Console.
For the sequence of API calls, you might be using a runner.
So you may store the lat-long values in variable and pass them to the other URL of google maps.
Request 1: You need to store value of lat-long in environment
let resp = pm.response.json();
pm.environment.set("latitude",resp.lat);
pm.environment.set("longitude",resp.longitude);
postman.setNextRequest("Googlemaps"); // need to pass request name(used in postman) which need to be called
Request 2: In runner, for the second request add below line in tests to stop the test:
postman.setNextRequest(null);
This is pretty old but I found a hacky way to do this.
Step 0. Have your URL
There are plenty of ways using the pre/post script features in Postman to generate this from some API output
Step 1. Setup a simple API running on localhost launching the browser
For me I did this using express and node, something like
const express = require('express');
const app = express();
const open = require('open');
const bodyParser = require('body-parser');
const port = 1;
app.use(bodyParser.urlencoded({ extended: true }));
app.get('/open-url', (req, res) => {
open(req.body.q);
res.send('Hello World!');
});
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`);
});
Running on http://localhost:1.
Step 2. Create a GET request in Postman
A simple example
curl --location --request GET 'http://localhost:1/open-url' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'q=http://google.com'
I want to read the request cookie during a test written with the puppeteer. But I noticed that most of the requests I inspect have only referrer and user-agent headers. If I look at the same requests in Chrome dev tools, they have a lot more headers, including Cookie. To check it out, copy-paste the code below into https://try-puppeteer.appspot.com/.
const browser = await puppeteer.launch();
const page = await browser.newPage();
page.on('request', function(request) {
console.log(JSON.stringify(request.headers, null, 2));
});
await page.goto('https://google.com/', {waitUntil: 'networkidle'});
await browser.close();
Is there a restriction which request headers you can and can not access? Is it a limitation of Chrome itself or puppeteer?
Thanks for suggestions!
I also saw this when I was trying to use Puppeteer to test some CORS behaviour - I found the Origin header was missing from some requests.
Having a look around the GitHub issues I found an issue which mentioned Puppeteer does not listen to the Network.responseReceivedExtraInfo event of the underlying Chrome DevTools Protocol, this event provides extra response headers not available to the Network.responseReceived event. There is also a similar Network.requestWillBeSentExtraInfo event for requests.
Hooking up to these events seemed to get me all the headers I needed. Here is some sample code which captures the data from all these events and merges it onto a single object keyed by request ID:
// Setup.
const browser = await puppeteer.launch()
const page = await browser.newPage()
const cdpRequestDataRaw = await setupLoggingOfAllNetworkData(page)
// Make requests.
await page.goto('http://google.com/')
// Log captured request data.
console.log(JSON.stringify(cdpRequestDataRaw, null, 2))
await browser.close()
// Returns map of request ID to raw CDP request data. This will be populated as requests are made.
async function setupLoggingOfAllNetworkData(page) {
const cdpSession = await page.target().createCDPSession()
await cdpSession.send('Network.enable')
const cdpRequestDataRaw = {}
const addCDPRequestDataListener = (eventName) => {
cdpSession.on(eventName, request => {
cdpRequestDataRaw[request.requestId] = cdpRequestDataRaw[request.requestId] || {}
Object.assign(cdpRequestDataRaw[request.requestId], { [eventName]: request })
})
}
addCDPRequestDataListener('Network.requestWillBeSent')
addCDPRequestDataListener('Network.requestWillBeSentExtraInfo')
addCDPRequestDataListener('Network.responseReceived')
addCDPRequestDataListener('Network.responseReceivedExtraInfo')
return cdpRequestDataRaw
}
That's because your browser sets a bunch of headers depending on settings and capabilities, and also includes e.g. the cookies that it has stored locally for the specific page.
If you want to add additional headers, you can use methods such as:
page.setExtraHTTPHeaders docs here.
page.setUserAgent docs here.
page.setCookies docs here.
With these you can mimic the extra headers that you see your Chrome browser dispatching.