Postman Console Output Clickable URL - postman

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'

Related

Postman: Set a request header from the output of a program

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);
});
}

Log all response cookies in Postman

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.

Virtual Hosting on Next.js app with Apollo GraphQL

I have a webapp made with Next.js and Apollo as show in example with-apollo. I want to serve multiple domains with my webapp (name-based virtual hosting). Unfortunately HttpLink of ApolloClient requires absolute server URL with domain but this makes backend app unable to recognize domain which user really visited. Is there a way to configure HttpLink with a dynamic URL based on real request or use relative URL or anything else?
Either use an Apollo Link to intercept the query and set uri property on the context
const authMiddleware = setContext((operation, { uri }) => {
return refreshToken().then(res => ({
uri: this.getURI()
})
}))
Or intercept the request with Angular's HttpClient interceptor and change the endpoint.
https://github.com/apollographql/apollo-angular/tree/master/packages/apollo-angular-link-http#options
Source: Updating uri of apollo client instance
The NextPageContext object passed to getInitialProps includes the req object when called on the server-side. So you can do something like:
WithApollo.getInitialProps = async ctx => {
const { AppTree, req } = ctx
const linkBaseUrl = req ? req.protocol + '://' + req.get('host') : ''
...
}
You can then pass this base url down to createApolloClient along with the initial state and prepend your HttpLink's url with it. On the client side, this will prepend an empty string (you only need the full URL on the server).

Missing request headers in puppeteer

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.

Parse S3FileAdapter

I currently have a parse-server deployment working however every time I upload a file it stores it with the GridStore file adapter instead of the S3 one. My app JS looks like this:
// Example express application adding the parse-server module to expose Parse
// compatible API routes.
var express = require('express');
var ParseServer = require('parse-server').ParseServer;
var path = require('path');
var S3Adapter = require('parse-server').S3Adapter;
var databaseUri = process.env.DATABASE_URI || process.env.MONGOLAB_URI;
if (!databaseUri) {
console.log('DATABASE_URI not specified, falling back to localhost.');
}
var api = new ParseServer({
databaseURI: databaseUri || 'mongodb://localhost:27017/dev',
cloud: process.env.CLOUD_CODE_MAIN || __dirname + '/cloud/main.js',
appId: process.env.APP_ID || 'somAppId',
masterKey: process.env.MASTER_KEY || '', //Add your master key here. Keep it secret!
serverURL: process.env.SERVER_URL || 'http://localhost:1337/parse', // Don't forget to change to https if needed
liveQuery: {
classNames: ["Posts", "Comments"] // List of classes to support for query subscriptions
},
filesAdapter: new S3Adapter(
"S31",
"S32",
"bucket-name",
{directAccess: true}
)
});
// Client-keys like the javascript key or the .NET key are not necessary with parse-server
// If you wish you require them, you can set them as options in the initialization above:
// javascriptKey, restAPIKey, dotNetKey, clientKey
var app = express();
// Serve static assets from the /public folder
app.use('/public', express.static(path.join(__dirname, '/public')));
// Serve the Parse API on the /parse URL prefix
var mountPath = process.env.PARSE_MOUNT || '/parse';
app.use(mountPath, api);
// Parse Server plays nicely with the rest of your web routes
app.get('/', function(req, res) {
res.status(200).send('Make sure to star the parse-server repo on GitHub!');
});
// There will be a test page available on the /test path of your server url
// Remove this before launching your app
app.get('/test', function(req, res) {
res.sendFile(path.join(__dirname, '/public/test.html'));
});
var port = process.env.PORT || 1337;
var httpServer = require('http').createServer(app);
httpServer.listen(port, function() {
console.log('parse-server-example running on port ' + port + '.');
});
// This will enable the Live Query real-time server
ParseServer.createLiveQueryServer(httpServer);
After I deploy I do not get any errors. Everything seems to be running fine. However, when I upload a file it goes to my monglab DB instead of my S3 storage. Do I need to do something else to configure this? I'm using the docs as a reference to configure this:
https://github.com/ParsePlatform/parse-server/wiki/Configuring-File-Adapters
I also noticed that on the parse-server repo it does not have an S3FileAdapter:
https://github.com/ParsePlatform/parse-server/tree/master/src/Adapters/Files
Any help will be greatly appreciated!
Thanks,
David
mLab db do not store files. It only stores the link of file. You need to upload files to S3 first. If successful, Parse server will return a filename, then, write the name to the db. I use curl command to check file-writing. If it works, your settings should be okay.
curl -X POST \
-H "X-Parse-Application-Id: YOUR-APP-ID" \
-H "X-Parse-REST-API-Key: YOUR-KEY" \
-H "Content-Type: text/plain" \
-d 'Hello, it is me!' \
http://your-parse-server/parse/files/filename.txt
I'm using this script and it's work fine
filesAdapter: new S3Adapter(
"ACCESS_KEY",
"SECRET_KEY",
"BUCKET_NAME",
"REGION"
)
Facing the exact same problem, when gone through in parse-server/lib/Adapters/AdapterLoader.js, I found filesAdapter allowed custom module with configuration options or function. So I tried with below solution which works fine for me.
var S3Adapter = require('parse-server').S3Adapter;
var api = new ParseServer({
...
filesAdapter: () => {
return new S3Adapter("ACCESS_KEY", "SECRET_KEY", "BUCKET_NAME")
}
...
});