Reputation: 41
Okay, I will go crazy if someone doesn't explain to me what is going wrong. Its whether too simple or I am too stupid.
Here's the code, feel free to copy-paste it in your machines and RUN IT MORE THAN ONCE WITHOUT RESTARTING THE SERVER. I REPEAT, DO NOT RESTART THE SERVER.
const { OAuth2Client } = require('google-auth-library');
const router = require('express')();
const open = require('open');
const fs = require('fs');
const path = require('path');
const { google } = require('googleapis');
const { Buffer } = require('node:buffer');
var stream = require('stream');
const { redirect_uris, client_id, client_secret } = require('./config/config');
const filePath = path.join(__dirname + '/output/image.png');
async function pushToDrive(req, res) {
try {
const oAuth2Client = await getAuthenticatedClient();
console.log("zero")
// After acquiring an access_token, you may want to check on the audience, expiration,
// or original scopes requested. You can do that with the `getTokenInfo` method.
// const tokenInfo = await oAuth2Client.getTokenInfo(
// oAuth2Client.credentials.access_token
// );
const drive = google.drive({
version: 'v3',
auth: oAuth2Client,
});
console.log("first")
const response = await drive.files.create({
resource: {
mimeType: 'image/png'
},
media: {
// mimeType: 'application/pdf',
body: fs.createReadStream(filePath)
},
fields: 'id'
});
console.log("second")
console.log(response.data.id);
res.send(response.data.id);
// return response.data.id;
} catch (error) {
console.error(error);
}
}
/**
* Create a new OAuth2Client, and go through the OAuth2 content
* workflow. Return the full client to the callback.
*/
function getAuthenticatedClient() {
return new Promise((resolve, reject) => {
// create an oAuth client to authorize the API call. Secrets are kept in a `keys.json` file,
// which should be downloaded from the Google Developers Console.
try {
const oAuth2Client = new OAuth2Client(
client_id,
client_secret,
redirect_uris
);
// Generate the url that will be used for the consent dialog.
const authorizeUrl = oAuth2Client.generateAuthUrl({
access_type: 'offline',
scope: 'https://www.googleapis.com/auth/drive.file',
});
open(authorizeUrl, { wait: false }).then(cp => cp.unref());
router.get('/oauthcallback', async (req, res) => {
// res.sendFile(path.join(__dirname, '/public/info.html'));
// Now that we have the code, use that to acquire tokens.
const r = await oAuth2Client.getToken(req.query.code);
// Make sure to set the credentials on the OAuth2 client.
oAuth2Client.setCredentials(r.tokens);
console.info('Tokens acquired.');
resolve(oAuth2Client);
console.log("here2");
res.send("You are authenticated");
res.end();
return resolve(oAuth2Client);
});
} catch (error) {
reject(error);
}
});
}
router.get('/xyz', pushToDrive);
router.listen(5000);
// pushToDrive();
// module.exports = { pushToDrive, getAuthenticatedClient, router };
The output I get in my backend console ->
Tokens acquired.
here2
zero
first
second
1rVk4Jjm0h_tO-x-BIDm1iWVDzZ4KfEJ3
Tokens acquired.
here2
Tokens acquired.
here2
As you can see, I got the file_id once - the first time I ran through the Drive upload. That's a success. But any subsequent tries stop at the resolution of oAuth2Client
. WHY? If its the event loop, then someone explain me why its not returning control to the parent function. From running the debugger, I found out that Nodejs...just stops at resolve(oAuth2Client)
.
Upvotes: 0
Views: 343
Reputation: 1197
There are two mistakes in your code:
1. You cannot define route inside another route. Your function
Sorry, you can - only have to take care the routes are called in proper sequence.pushToDrive
which you call inside /xyz
route defines new route to /oauthcallback
.
resolve
in new Promise
is a bit problematic, as it is called right after the whole function is started - it does not wait until something calls the promise.resolve
I would try something like this:
app.js
const oAuth2Client = new OAuth2Client(
client_id,
client_secret,
redirect_uris
);
const authorizeClient = () => {
const authorizeUrl = oAuth2Client.generateAuthUrl({
access_type: 'offline',
scope: 'https://www.googleapis.com/auth/drive.file',
});
open(authorizeUrl, { wait: false }).then(cp => cp.unref());
async function pushToDrive(req, res) {
try {
const drive = google.drive({
version: 'v3',
auth: oAuth2Client,
});
console.log("first")
const response = await drive.files.create({
resource: {
mimeType: 'image/png'
},
media: {
// mimeType: 'application/pdf',
body: fs.createReadStream(filePath)
},
fields: 'id'
});
console.log("second")
console.log(response.data.id);
res.send(response.data.id);
} catch (error) {
console.error(error);
}
}
router.get('/oauthcallback', async (req, res) => {
const r = await
oAuth2Client.getToken(req.query.code);
oAuth2Client.setCredentials(r.tokens);
console.info('Tokens acquired.');
});
router.get('/xyz', pushToDrive);
router.listen(5000);
Upvotes: 1