CORS error while trying to access Flask API - reactjs

I have a React front end and Flask Backend. There's a Long-Running Task in the Back end which is gonna start when I submit the Job from the Front end. I assigned 2 Buttons on the front end to Submit the Job and the Other One to Check the status of the Job and Retrieve Data if the Job Is Finished.
Front End Job Submit Function
const sendSubmitRequest = async () => {
try {
const resp = await axios.get('http://localhost:8000/submit-job/'+embedId);
if (resp.status === 202) {
setTaskId(resp.data.task_id)
console.log(resp.data);
alert("Job Submision Success..")
console.log("Job Submitted Successfully...")
} else {
alert("Job Submision Failed... \nCheck If the Video URL Is Correct")
}
} catch (err) {
// Handle Error Here
console.error(err);
}
};
Front End Check Job Status Function
const checkJobStatusTime = async () => {
let refreshId = null
try {
const refreshId = setInterval(async () => {
const resp = await axios.get('http://localhost:8000/get-result/'+taskId);
if (resp.status === 200 && resp.data.status === 'success') {
const resl = resp.data.result;
console.log(resl)
setData(resl);
alert("Data Retrieved Successfully...")
clearInterval(refreshId);
}
else if(resp.status === 200 && resp.data.status === 'not_found') {
clearInterval(refreshId);
} else {
console.log("Job Still Runing...")
}
}, 3000);
} catch(e) {
console.log(e);
clearInterval(refreshId);
}
}
In the Flask Back End, I have 2 Functions corresponds to the 2 Front End Functions
Backend Handle Job Submit Function
#app.route('/submit-job/<video_id>')
#cross_origin(origin='*', headers=['Content-Type', 'Authorization'])
def handle_submit(video_id):
job_id = id_generator()
executor.submit_stored(job_id, test_func, video_id)
return jsonify({'status': 'success', 'task_id': job_id, 'message': 'Job Submitted Successfully'}), 202
Backend Handle Check Job Status Function
#app.route('/get-result/<task_id>')
#cross_origin(origin='*', headers=['Content-Type', 'Authorization'])
def get_result(task_id):
if task_id in executor.futures._futures.keys():
if executor.futures.done(task_id):
future = executor.futures.pop(task_id)
return jsonify({'status': 'success',
'message': 'Job Completed Successfully',
'result': future.result()}), 200
else:
return jsonify({'status': executor.futures._state(task_id),
'message': 'Job Still Running',
'result': None}), 200
else:
return jsonify({'status': 'not_found',
'message': 'Task Id Cannot be Found.',
'result': None}), 200
Import 'cross_origin'
from flask_cors import cross_origin
PROBLEM:
When I Assigned the 2 Functions to the 2 Buttons Separately Everything works fine As Expected. However, If I try to call the Check status Function with the Job submit Function Like this,
const sendSubmitRequest = async () => {
try {
const resp = await axios.get(endPoint+'/youtube/submit-job/'+embedId);
if (resp.status === 202) {
setTaskId(resp.data.task_id);
console.log("Job Submitted Successfully...")
// Calling the Status Check Function
checkJobStatusTime();
} else {
alert("Job Submision Failed... \nCheck If the Video URL Is Correct")
}
} catch (err) {
// Handle Error Here
console.error(err);
}
};
This gives the CORs error.
Access to XMLHttpRequest at 'http://localhost:8000/get-result/' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Can someone help me figure out why this is Happening?

Try to use the #cross_origin decorator without any arguments.
As it's written in the Documentation:
In the simplest case, simply use the default parameters to allow all origins in what is the most permissive configuration
Also headers is not a valid parameter for this decorator.
You might want to use allow_headers.

Related

Cannot update or save data on second or next user in mongodb

May I know what is the problem with my code for the backend. I try to create a place and update it in the user database. The problem is If I only have 1 user. The database can create and update the data but if I have more than 2 then, the data cannot be updated or created. Here is my code. I have been working on this part for so long, that I cannot find the solution.
const createFile = async (req, res, next) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return next(
new HttpError('Invalid inputs passed, please check your data.', 422)
);
}
const { userId, Dataset } = req.body;
const createdFile = new File({
userId,
Dataset,
});
let user;
try {
user = await User.findById(userId);
} catch (err) {
const error = new HttpError(
'Creating place failed, please try again 1',
500
);
return next(error);
}
if (!user) {
const error = new HttpError('Could not find user for provided id', 404);
return next(error);
}
try {
const sess = await mongoose.startSession();
sess.startTransaction();
await createdFile.save({ session: sess });
user.Dataset.push(createdFile);
await user.save({ session: sess });
await sess.commitTransaction();
} catch (err) {
const error = new HttpError(
'Creating place failed, please try again.2',
500
);
return next(error);
}
res.status(201).json({ files: createdFile });
};
The error message that I got
Error: User validation failed: _id: Error, expected `_id` to be unique. Value: `62c661c629d1cb99768efd05`
at ValidationError.inspect (C:\Users\acit\Desktop\FYP Code\FYP Code\backend2\node_modules\mongoose\lib\error\validation.js:48:26)
at internal/per_context/primordials.js:23:32
at formatValue (internal/util/inspect.js:783:19)
at inspect (internal/util/inspect.js:337:10)
at formatWithOptionsInternal (internal/util/inspect.js:2016:40)
at formatWithOptions (internal/util/inspect.js:1898:10)
at console.value (internal/console/constructor.js:323:14)
at console.log (internal/console/constructor.js:358:61)
at createFile (C:\Users\acit\Desktop\FYP Code\FYP Code\backend2\controllers\files-controller.js:102:13)
at processTicksAndRejections (internal/process/task_queues.js:93:5) {
errors: {
_id: ValidatorError: Error, expected `_id` to be unique. Value: `62c661c629d1cb99768efd05`
at validate (C:\Users\acit\Desktop\FYP Code\FYP Code\backend2\node_modules\mongoose\lib\schematype.js:1321:13)
at C:\Users\acit\Desktop\FYP Code\FYP Code\backend2\node_modules\mongoose\lib\schematype.js:1297:24
at processTicksAndRejections (internal/process/task_queues.js:93:5) {
properties: [Object],
kind: 'unique',
path: '_id',
value: new ObjectId("62c661c629d1cb99768efd05"),
reason: undefined,
[Symbol(mongoose:validatorError)]: true
}
},
_message: 'User validation failed'
}
It already settle, I reroll the mongoose-unique-validator to 2.0.3 version
I use this command
npm install mongoose-unique-validator#2.0.3 --legacy-peer-deps
hope that someone with same issues as mine find my post and can help them to solve the same issues

How To Circumvent 504 Errors

I am working in ReactJs and one of the main aspects of our project is the ability to upload a scorecard and have all of its results parsed and placed into objects. However, due to the nature of these pdfs that get uploaded, there's a LOT of information, an average of 12-14 pages.
Most of the information is irrelevant, I usually will only need pages 5-7, but users will be users, and they upload all 12.
I am using the pdfParser API which is very good, we're not looking for replacements on that. However, due to how large the file is, if I am somewhere with only half-decent connection, I am hit with a 504 error since the process takes so long. If I have good to great connection, there's no issue.
This being said I have two questions:
Is there a way to extend the amount of time that needs to elapse before my computer gives up on the process
Is there a way to parse only SOME of the pages that get submitted?
The relevant code will be shown below...
var url = 'https://pdftables.com/api?key=770oukvvx1wl&format=xlsx-single';
const pdfToExcel = (pdfFile) => {
var req = request.post({encoding: null, url: url}, async function (err, resp, body) {
if (!err && resp.statusCode == 200) {
fs.writeFile(`${pdfFile.path}.xlsx`, body, function(err) {
if (err) {
console.log('error writing file');
}
});
} else {
console.log('error retrieving URL');
};
});
var form = req.form();
form.append('file', fs.createReadStream(`./${pdfFile.path}`));
}
const parseExcel = async (file) => {
let workSheetsFromFile;
if (file.path.search(".xlsx") === -1) {
const filePath = await path.resolve(`./${file.path}.xlsx`)
workSheetsFromFile = await xlsx.parse(`./${file.path}.xlsx`);
await fs.unlinkSync(`./${file.path}`)
await fs.unlinkSync(filePath)
return workSheetsFromFile[0].data
}
if (file.path.search(".xlsx") !== -1) {
const filePath = await path.resolve(`./${file.path}`)
workSheetsFromFile = await xlsx.parse(`./${file.path}`);
await fs.unlinkSync(filePath)
return workSheetsFromFile[0].data
}
}

How to keep a count of number of requests when using mock service worker to test a React App?

In my app, the user enters their date of birth, a request is sent, and if it matches with the DOB in the database, they are sent to the next page. If it does not match, they are presented with the number of attempts they have left until their link is no longer valid. They have 3 attempts.
My question is, how would I mock this functionality using mock service worker? I would need to keep a count of the number of times this request has been attempted and failed.
Here is the code snippet of the handler, as you can see I have hardcoded the "1" after "Auth attempts" for now.
rest.post(
'https://myapiaddress/auth',
(req, res, ctx) => {
const enteredDateOfBirth = req.body.data.date_of_birth
let returnResult
if (enteredDateOfBirth === '1988-10-01') {
returnResult = res(
ctx.status(200),
ctx.json({
data: {
basic: 'fdafhaioubeaufbaubsaidbnf873hf8faoi'
}
})
)
} else {
returnResult = res(
ctx.status(400),
ctx.json({
errors: [
{ code: 89, message: 'Wrong date of birth. Auth attempts: 1' }
]
})
)
}
return returnResult
}
)
]
My jest test in which I confirm the incorrect date 3 times:
// 1st attempt
userEvent.click(confirmBtn)
const warningAttemptsNum1 = await screen.findByText('1/3 attempts')
const dateEntered = screen.getByText('(12/10/2010)')
expect(warningAttemptsNum1).toBeInTheDocument()
expect(dateEntered).toBeInTheDocument()
// 2nd attempt
userEvent.click(confirmBtn)
const warningAttemptsNum2 = await screen.findByText('2/3 attempts')
expect(warningAttemptsNum2).toBeInTheDocument()
userEvent.click(confirmBtn)
// Entering 3 times shows "link no longer valid" screen
userEvent.click(confirmBtn)
const linkNoLongerValidText = await screen.findByText(
'This link is no longer valid'
)
expect(linkNoLongerValidText).toBeInTheDocument()
Your general idea is correct: you can keep a track of the count of requests made by incrementing a number in the response resolver.
Here's how I'd recommend doing it:
function withTimes(handler) {
let attempts = 0
return (req, res, ctx) => {
attempts++
handler(req, res, ctx, attempts)
}
}
rest.post('/endpoint', withTimes((req, res, ctx, attempts) => {
const MAX_ATTEMPTS = 3
const dob = req.body.data.date_of_birth
if (dob === '1988-10-01') {
return res(ctx.json({ data: { basic: 'abc-123' }}))
}
return res(
ctx.status(400),
ctx.json({
errors: [
{
code: 89,
message: `Wrong date of birth. Attempts left: ${MAX_ATTEMPTS - attempts}`
}
]
})
)
}))
I also see that the response body structure you use is very similar to such of GraphQL. Note that you should use the GraphQL API to handle GraphQL operations.

How to write to google finance API?

I know how to read from the google finance api, it is pretty simple.
But when I try to write I get the following error:
Error: Request had insufficient authentication scopes
This is my code:
const fs = require('fs');
const readline = require('readline');
const {google} = require('googleapis');
// If modifying these scopes, delete token.json.
const TOKEN_PATH = 'token.json';
// Load client secrets from a local file.
fs.readFile('./GoogleFinanceApi/credentials.json', (err, content) => {
if (err) return console.log('Error loading client secret file:', err);
// Authorize a client with credentials, then call the Google Sheets API.
authorize(JSON.parse(content), appendData);
});
Here ^ in the append data is where I am calling the function, it works when i do the listMajors but not when I do the appendData...
function authorize(credentials, callback) {
const {client_secret, client_id, redirect_uris} = credentials.installed;
const oAuth2Client = new google.auth.OAuth2(
client_id, client_secret, redirect_uris[0]);
// Check if we have previously stored a token.
fs.readFile(TOKEN_PATH, (err, token) => {
if (err) return getNewToken(oAuth2Client, callback);
oAuth2Client.setCredentials(JSON.parse(token));
callback(oAuth2Client);
});
}
function listMajors(auth) {
const sheets = google.sheets({version: 'v4', auth});
sheets.spreadsheets.values.get({
spreadsheetId: '1ckHZsL2fnWVATmXljlewm-6qBo62B0qmu0w_2QdSpGA',
range: 'Sheet1!A2:E',
}, (err, res) => {
if (err) return console.log('The API returned an error: ' + err);
const rows = res.data.values;
if (rows.length) {
console.log('Name, Major:');
// Print columns A and E, which correspond to indices 0 and 4.
rows.map((row) => {
console.log(`${row[0]}, ${row[4]}`);
});
} else {
console.log('No data found.');
}
});
}
function appendData(auth) {
var sheets = google.sheets('v4');
sheets.spreadsheets.values.append({
auth: auth,
spreadsheetId: '1ckHZsL2fnWVATmXljlewm-6qBo62B0qmu0w_2QdSpGA',
range: 'Sheet1!A2:B', //Change Sheet1 if your worksheet's name is something else
valueInputOption: "USER_ENTERED",
resource: {
values: [ ["Void", "Canvas", "Website"], ["Paul", "Shan", "Human"] ]
}
}, (err, response) => {
if (err) {
console.log('The API returned an error: ' + err);
return;
} else {
console.log("Appended");
}
});
}
What am I doing wrong? I have read some posts and they say they didn't add the resource so I tried to fix that but still nothing works...
Probably the issue is in google.sheets in appendData. Perhaps you need to pass auth to google.sheets before you access sheets as how you are doing in listMajors but you are passing auth to the sheets instead of google.sheets. This might be an issue
Can you try below updated code
function appendData(auth) {
const sheets = google.sheets({version: 'v4', auth})
sheets.spreadsheets.values.append({
spreadsheetId: '1ckHZsL2fnWVATmXljlewm-6qBo62B0qmu0w_2QdSpGA',
range: 'Sheet1!A2:B', //Change Sheet1 if your worksheet's name is something else
valueInputOption: "USER_ENTERED",
resource: {
values: [ ["Void", "Canvas", "Website"], ["Paul", "Shan", "Human"] ]
}
}, (err, response) => {
if (err) {
console.log('The API returned an error: ' + err);
return;
} else {
console.log("Appended");
}
});
}

Balanced-Payments Try Catch response

I've attempting to learn how to set up credit card payments and using a Balanced Payments test marketplace. I haven't ever set up a try catch statement before and I am having some trouble with processing the response.
Here is my controller try/catch statement:
try{
$card->debits->create(array(
"amount" => $amount,
"appears_on_statement_as" => "test",
"description" => $invoiceId,
"order" => $order,
));
} catch (Balanced\Errors\Declined $e) {
$this->arrResponse['status'] = $e->getMessage();
return Response::json($this->arrResponse);
}
$invoice->save();
// send email function...
//redirect
$this->arrResponse['status'] = SUCCESS;
return Response::json($this->arrResponse);
I can see the error on chrome developer tools, but I can't make it appear on my view.
Chrome dev tools 500 internal server error statement:
error: {type: "Balanced\Errors\Declined", message: "",…}
file: "/Applications/MAMP/htdocs/testcc/vendor/balanced/balanced/src/Balanced/Errors/Error.php"
line: 42
message: ""
type: "Balanced\Errors\Declined
processpayment.js file:
jQuery.post(baseURL+'/processPayment', {
uri: fundingInstrument.href,
amount: amount,
invoiceId: invoiceId,
}, function(r) {
// backend response
if (r.status === 200) {
$('#msgSection').empty().removeClass('alert-error alert-success').addClass('alert-success').text(' payment has been received').show();
} else {
// failure from backend
$('#msgSection').empty().removeClass('alert-success').addClass('alert-warning').text('error').show();
}
});
When test card is processed successfully, everything works and success message appears on my view. However, when I use a test card that is declined, no message is sent to my view. Anyone see what I am doing wrong?
try to check balanced-php client testsuite to see how they use try catch block from here
so your code would be like.
try{
$card->debits->create(array(
"amount" => $amount,
"appears_on_statement_as" => "test",
"description" => $invoiceId,
"order" => $order,
));
} catch (Balanced\Errors\Declined $e) {
$this->arrResponse['status'] = $e->category_code;
return Response::json($this->arrResponse);
}
$invoice->save();
// send email function...
//redirect
$this->arrResponse['status'] = SUCCESS;
return Response::json($this->arrResponse);
$e->category_code will be either funding-destination-declined or authorization-failed or card-declined

Resources