Failed to launch chrome! spawn ...node_modules/puppeteer/.../chrome ENOENT TROUBLESHOOTING when using Puppeteer - pdf-generation

I was trying to build a quick lambda that prints a pdf with a specific url, but I get this error: Failed to launch chrome! spawn ...node_modules/puppeteer/.../chrome ... TROUBLESHOOTING
Methods mentioned here : https://github.com/GoogleChrome/puppeteer/issues/807#issuecomment-366529860 did not help me.
The code I'm using:
const browser = await puppeteer.launch({
headless: true,
executablePath: '../../node_modules/puppeteer/.local-chromium/linux-624487/chrome-linux/chrome',
args: ['--no-sandbox', '--disable-setuid-sandbox'],
});
try {
const result = await exports.run(browser);
callback(null, result);
} catch (e) {
callback(e);
}
...
exports.run = async (browser) => {
// implement here
// this is sample
const page = await browser.newPage();
await page.goto('https://www.google.com', {
waitUntil: ['domcontentloaded', 'networkidle0']
});
console.log((await page.content()).slice(0, 500));
await page.type('#lst-ib', 'aaaaa');
// avoid to timeout waitForNavigation() after click()
await Promise.all([
// avoid to
// 'Cannot find context with specified id undefined' for localStorage
page.waitForNavigation(),
page.click('[name=btnK]'),
]);
// cookie and localStorage
await page.setCookie({
name: 'name',
value: 'cookieValue'
});
console.log(await page.cookies());
console.log(await page.evaluate(() => {
localStorage.setItem('name', 'localStorageValue');
return localStorage.getItem('name');
}));
const result = await page.pdf({
path: 'hn.pdf',
format: 'A4'
});
console.log(` typeof : ${typeof result}, pdf: ${result}`);
await page.close();
return 'done';
};

check this path =>
\node_modules\puppeteer.local-chromium\win32-818858\chrome-win
you will notice chrome.exe will not exist, now got back one step =>
*\node_modules\puppeteer.local-chromium*
you will find zip file "chrome-win" extract it and move it int to =>
\node_modules\puppeteer.local-chromium\win32-818858
Now you may check it will work.

Related

Puppeteer downloads blank PDF instead of the one expected, with content

I have to download a pdf, but it requires first to collect cookies, by visiting the page which hosts the PDF link.
I click the link but a blanc PDF is downloaded with same pages number as the expected one.
(async () => {
const browser = await puppeteer.launch({
dumpio: true,
headless: false,
devtools: true,// I want to see what's going on
})
const [page] = await browser.pages();
page.on('console', msg => console.log(msg.text()));
await page.goto(url_cookie, { waitUntil: ['domcontentloaded', 'networkidle0', 'load'] });
page._client.send('Page.setDownloadBehavior', { behavior: 'allow', downloadPath: './', });
page.once('response', async (response) => {
if (response.url() !== url_pdf) return;
console.log('resp', response.url());
});
const css = 'a[href="' + url + '"]';
await page.waitForSelector(css)
const eval = async css => {
const a = document.querySelector(css);
console.log(a)
return fetch(a.href, {
method: 'GET',
credentials: 'include',
}).then(r => r.text())
};
const txt = await page.evaluate(eval, [css]);
fs.writeFileSync('./test.pdf', txt,)
await page.close();
await browser.close();
})();

Async Lambda function returning null on calling DynamoDB

I am new to async functions and promises. I have written a Lambda function which queries a DynamoDB table and returns the result. The code is executing inside the callback success block and I am able to see the response in the log from the console.log(res) line. However the Lambda response is always showing as null, i.e. the response object below is not returned at all. I was able to make this work using a Synchronous Lambda function using a callback to return the data. Can you please suggest what I may be doing incorrectly.
const doc = require('dynamodb-doc');
var dynamodbclient;
const tablename = process.env.TABLE_NAME;
exports.handler = async(event) => {
if (!dynamodbclient) {
dynamodbclient = new doc.DynamoDB();
}
let id = event.params.id;
let queryparams = {
TableName: 'table-name',
Key: { id: id }
};[![enter image description here][1]][1]
var getItemsCallback = (err, res) => {
console.log('inside');
if (err) {
}
else {
console.log('success');
console.log(res);
const response = {
statusCode: 200,
body: JSON.stringify('Hello from Lambda!'),
};
return response;
}
};
var item = await dynamodbclient.getItem(queryparams, getItemsCallback).promise();
};
Your callback is still executing after the promise resolves, so the lambda will terminate and your callback will not finish.
Try:
try {
const item = await dynamodbclient.getItem(queryparams).promise();
} catch (err) {}
console.log('success');
console.log(item);
const response = {
statusCode: 200,
body: JSON.stringify('Hello from Lambda!'),
};
return response;

How to get rid of 'return new Promise' and not to lose data?

In this case, there is nothing easier to wait until the data is received, and then resolve the Promise:
// Using Promise resolve/reject
module.exports = () => {
return new Promise(async (resolve, reject) => {
let doc = await Document();
doc.on('data', async (data) => {
resolve(data);
});
})
}
But what do I do in this case?
// Using async/await
module.exports = async () => {
let doc = await Document();
doc.on('data', (data) => {
// ???
});
}
You still need the new Promise, you just should use it as the operand of an await inside the async function, not using an async function as the executor:
module.exports = async () => {
const doc = await Document();
return new Promise(resolve, reject) => {
doc.on('data', resolve);
});
};
However, I would recommend to use once instead of on so that the event handler is removed after the first occurrence of the event - the promise can be resolve only once anyway. Also if you have node v11.13.0 or higher you can just use the events.once method so that you don't have to build the promise yourself - and it also handles error events correctly:
const { once } = require('events');
module.exports = async () => {
const doc = await Document();
return once(doc, 'data');
};

use async/await instead of (.then)

I am trying to replace .then with async/await
here is my code
export const loginUser = (userData) => async dispatch => {
try {
await axios.post('/api/users/login', userData);
// Save to localStorage
const {token} = res.data;
// Save token to local storage
localStorage.setItem('jwtToken', token);
// Set token to Auth header
setAuthToken(token);
// Decode to get user data
const decoded = jwt_decode(token);
// set current user
dispatch(setCurrentUser(decoded));
} catch (err) {
dispatch({
type: GET_ERRORS,
payload: err.response.data
})
}
};
and then this is the error
Unhandled Rejection (TypeError): Cannot read property 'data' of
undefined ▶ 6 stack frames were collapsed.

How to use async and await in gmail read message API

I tried using async/await instead of the callback for reading the Gmail
Here is the code snippet
const {google} = require('googleapis');
async function getRecentMessageBody(auth) {
const gmail = google.gmail({version: 'v1', auth});
try{
const messageId = await gmail.users.messages.list({
userId: 'me',
labelIds: 'INBOX',
maxResults: 1
});
const message = await gmail.users.messages.get({
userId: 'me',
id: messageId.data.messages[0].id,
format : 'full'
});
const value = base64url.decode(message.data.payload.body.data);
console.log(messageId);
//return value ;
}
catch(error) {
console.log('Error occurs while reading mail :'+ error);
throw error;
}
}
But the messageId is undefined
whereas if i use
gmail.users.labels.list({
userId: 'me',
}, (err, res) => {
if (err) return console.log('The API returned an error: ' + err);
const labels = res.data.labels;
if (labels.length) {
console.log('Labels:');
labels.forEach((label) => {
console.log(`- ${label.name}`);
});
} else {
console.log('No labels found.');
}
});
how to fix the issue??
use promisfy to convert callback to promises

Resources