Access a remote api from frontend react.js without any server side code - reactjs

I am trying to access remote url from fetch/axios post api in react.js. Here is my code in react-
const requestOptions = {
method: 'POST',
crossDomain: true,
mode: 'cors', // no-cors, *cors, same-origin
credentials: 'same-origin', // include, *same-origin, omit
headers:{'Content-Type': 'application/x-www-form-urlencoded',
"Access-Control-Allow-Origin": "*",
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Allow-Methods': 'GET,POST,OPTIONS,DELETE,PUT'},
redirect: 'follow', // manual, *follow, error
referrerPolicy: 'no-referrer',
body:new URLSearchParams({
'store_id':'storeid',
'store_passwd':'storepass',
'total_amount':100,
'currency':'BDT',
'tran_id':'NF04',
'success_url':"https://tigrow.herokuapp.com",
'fail_url':"https://tigrow.herokuapp.com",
'cancel_url':"https://tigrow.herokuapp.com",
'cus_name':"nizam",
'cus_email':"test#test.com",
'cus_add1':"customer address",
'cus_add2':"customer address",
'cus_city':"Dhaka",
'cus_state':"Dhaka2",
'cus_postcode':"Dhaka",
'cus_country':"Bangladesh",
'cus_phone':"01700000000",
'cus_fax':"01700000000",
'ship_name':"Sha",
'ship_add1':"dhaka",
'ship_add2':"dhaka1",
'ship_city':"Dhaka1",
'ship_state':"Dhaka2",
'ship_postcode':"1000",
'ship_country':"Bangladesh",
'multi_card_name':"mastercard,visacard,amexcard",
'value_a':"ref001_A",
'value_b':"ref002_B",
'value_c':"ref003_C",
'value_d':"ref004_D",
'shipping_method':"No",
'product_name':"Test",
'product_category':"Test Category",
'product_profile':"general"
})
};
fetch(url, requestOptions)
.then(response =>console.log(response))
.then(data => console.log(data));
I want to get data from rempte api in react only, not any server side code. Here my content-type is application/x-www-form-urlencoded. How can I solve this problem only using react.js?

My remote API strictly mentioned that no call from client side code. Developer must need to call the API from server side and after completing the call developer should return the string url, not any json data. I followed the way and done the code in python and got the result. However my frontend was react. Here is the code snippet-
def sslcommerz_payment_gateway(request):
gateway_auth_details = PaymentGatewaySettings.objects.all().first()
settings = {'store_id':gateway_auth_details.store_id,
'store_pass': gateway_auth_details.store_pass,
'issandbox': True} #gateway_auth_details.store_pass, 'issandbox': False}
print(request.POST)
sslcommez = SSLCOMMERZ(settings)
post_body = {}
post_body['total_amount'] =request.POST.get('total_amount')
post_body['currency'] = request.POST.get('currency')
post_body['tran_id'] =unique_transaction_id_generator()
post_body['success_url'] = 'http://127.0.0.1:8000/api/payment/success/'
post_body['fail_url'] = 'http://127.0.0.1:8000/api/payment/faild/'
post_body['cancel_url'] = request.POST.get('cancel_url')
post_body['emi_option'] = 0
post_body['cus_name'] = request.POST.get('cus_name')
post_body['cus_email'] =request.POST.get("cus_email")
post_body['cus_phone'] = request.POST.get("cus_phone")
post_body['cus_add1'] = request.POST.get("cus_add1")
post_body['cus_city'] = request.POST.get("cus_city")
post_body['cus_state'] =request.POST.get("cus_state")
post_body['cus_postcode'] =request.POST.get("cus_postcode")
post_body['cus_country'] = request.POST.get("cus_country")
post_body['shipping_method'] ="NO"#request.POST.get("shipping_method")
post_body['multi_card_name'] = "mastercard,visacard,amexcard,mobilebank,internetbank,othercard"
post_body['num_of_item'] = request.POST.get("num_of_item")
post_body['product_name'] = request.POST.get("product_name")
post_body['product_category'] = request.POST.get("product_category")
post_body['product_profile'] = "Art(Hard Copy/Soft Copy)"
response = sslcommez.createSession(post_body)
print(response)
return 'https://sandbox.sslcommerz.com/gwprocess/v4/gw.php?Q=pay&SESSIONKEY=' + response["sessionkey"]
Finally I got the API response and returned a url.

Related

I'm trying to send a post request to a new route in flask/react.js, what am I doing wrong?

I am trying to send the contents of a flashcard to a backend route http://127.0.0.1:5000/post onClick and it works when I send the data to webhook.site but when I change it to http://127.0.0.1:5000/post I get the error " question = data['question' TypeError: 'NoneType' object is not subscriptable ". Here is the code for the fetch request: async function postData() {
try {
let result = await fetch('http://127.0.0.1:5000/post', {
method: 'POST',
mode: 'no-cors',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
key: `${Date.now()}`,
question: flashcard.question,
answer: flashcard.answer,
options: flashcard.options
})
});
} catch(e) {
console.log(e)
}
}
and here is the code for the backend route in flask:
#app.route('/post', methods=['GET', 'POST'])
def post():
data = request.get_json()
question = data['question']
answer = data['answer']
options = data['options']
key = data['key']
return jsonify({'question' : question, 'answer' : answer, 'options' : options, 'key' : key})
if __name__ == "__main__":
app.run(debug=True)
I get that the error is stating that "data" has no value which I assume means it's not recieving the JSON objects that I'm posting. It's weird because it works perfectly when I use a webhook.site url. can anyone help? thanks for your time!

How to fix the error when trying to access the API?

I want to generate token to do the CRUD operations in SharePoint Online list. I am able to generate the token in Postman. But I want that it automatically gets generated in my React app to do the CRUD operations. I copied the code snippet from the Postman and pasted in my React app, but it is throwing error. Here is the error :
UsingFetch.js:181 POST https://accounts.accesscontrol.windows.net/834fb7b4-624d-4de8-a977-2d46ad979bd9/tokens/OAuth/2 400 (Bad Request)
{"error":"invalid_request","error_description":"AADSTS900144: The request body must contain the following parameter: 'grant_type'.\r\nTrace ID: d2dcb2da-1aae-4af2-a3e3-aabc35ce4301\r\nCorrelation ID: c90dff14-b64d-4f47-a01c-dfe498ec2f40\r\nTimestamp: 2022-02-23 09:07:45Z","error_codes":[900144],"timestamp":"2022-02-23 09:07:45Z","trace_id":"d2dcb2da-1aae-4af2-a3e3-aabc35ce4301","correlation_id":"c90dff14-b64d-4f47-a01c-dfe498ec2f40","error_uri":"https://accounts.accesscontrol.windows.net/error?code=900144"}
Here is the screenshot of the
Here is the code snippet that I copied from Postman :
const generateToken = async () => {
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/x-www-form-urlencoded");
myHeaders.append(
"Cookie",
"esctx=AQABAAAAAAD--DLA3VO7QrddgJg7WevrQx7IG43UK7gipYHXtqZImLB1jfBLK4PTkZlgLq3BvpTizt3xt8EZQrpUJGa0hTnSdpRf-AenJvnGNABiv2cWYWSyJj9QNm-vWalRGHuDZ6Km_DaX_5CQHUa4H8U-osEGCM48buOyj0G819e1NoxuvoOD6fZvMI5nnDWZyjNa1mogAA; fpc=An1vbDtRI8BAiCLlUBBGpFXf9_srAQAAACDgp9kOAAAA; stsservicecookie=estsfd; x-ms-gateway-slice=estsfd"
);
var formdata = new FormData();
formdata.append("grant_type", "client_credentials");
formdata.append(
"client_id",
"myclientid"
);
formdata.append(
"client_secret",
"mysecretcode"
);
formdata.append(
"resource",
"00000003-0000-0ff1-ce00-000000000000/cooponline.sharepoint.com#834fb7b4-624d-4de8-a977-2d46ad979bd9"
);
var requestOptions = {
method: "POST",
headers: myHeaders,
body: formdata,
redirect: "follow",
};
await fetch(
"https://accounts.accesscontrol.windows.net/834fb7b4-624d-4de8-a977-2d46ad979bd9/tokens/OAuth/2",
requestOptions
)
.then((response) => response.text())
.then((result) => console.log(result))
.catch((error) => console.log("error", error));
};
Can anyone please provide me with a solution?
Thank you.
This error says what's wrong: The request body must contain the following parameter: 'grant_type'.
To fix this, just add it as a parameter (formData in this case). According to the SharePoint docs, this value must be set to client_credentials.
formdata.append(
"grant_type",
"client_credentials"
);
EDIT:
Apparently, the request body has an unusual format. You're trying to send it as application/json, but MS expects application/x-www-form-urlencoded like this:
POST /{tenant}/oauth2/v2.0/token HTTP/1.1 //Line breaks for clarity
Host: login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded
client_id=535fb089-9ff3-47b6-9bfb-4f1264799865
&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default
&client_secret=sampleCredentia1s
&grant_type=client_credentials
So, instead of passing formData object as the request body, you should wrap it into a string like this:
const body = Object.keys(formData)
.map(key => `${key}=${formData[key]}`)
.join('&');
and pass that as the body.

403 when upload file to S3 bucket using axios

I'm using axios to upload an audio file to AWS s3 bucket.
The workflow is: React => AWS API Gateway => Lambda.
Here is the backend Lambda code where generates the S3 presigned URL:
PutObjectRequest putObjectRequest = PutObjectRequest.builder()
.bucket(AUDIO_S3_BUCKET)
.key(objectKey)
.contentType("audio/mpeg")
.build();
PutObjectPresignRequest putObjectPresignRequest = PutObjectPresignRequest.builder()
.signatureDuration(Duration.ofMinutes(10))
.putObjectRequest(putObjectRequest)
.build();
PresignedPutObjectRequest presignedPutObjectRequest = s3Presigner.presignPutObject(putObjectPresignRequest);
AwsProxyResponse awsProxyResponse = new AwsProxyResponse();
awsProxyResponse.setStatusCode(HttpStatus.SC_OK);
awsProxyResponse.setBody(
GetS3PresignedUrlResponse.builder()
.s3PresignedUrl(presignedPutObjectRequest.url().toString())
.build().toString());
return awsProxyResponse;
Here is the java code to create the bucket:
private void setBucketCorsSettings(#NonNull final String bucketName) {
s3Client.putBucketCors(PutBucketCorsRequest.builder()
.bucket(bucketName)
.corsConfiguration(CORSConfiguration.builder()
.corsRules(CORSRule.builder()
.allowedHeaders("*")
.allowedMethods("GET", "PUT", "POST")
.allowedOrigins("*") // TODO: Replace with domain name
.exposeHeaders("ETag")
.maxAgeSeconds(3600)
.build())
.build())
.build());
log.info("Set bucket CORS settings successfully for bucketName={}.", bucketName);
}
In my frontend, here is the part that try to upload file:
const uploadFile = (s3PresignedUrl: string, file: File) => {
let formData = new FormData();
formData.append("file", file);
formData.append('Content-Type', file.type);
const config = {
headers: {
"Content-Type": 'multipart/form-data; boundary=---daba-boundary---'
//"Content-Type": file.type,
},
onUploadProgress: (progressEvent: { loaded: any; total: any; }) => {
const { loaded, total } = progressEvent;
let percent = Math.floor((loaded * 100) / total);
if (percent < 100) {
setUploadPercentage(percent);
}
},
cancelToken: new axios.CancelToken(
cancel => (cancelFileUpload.current = cancel)
)
};
axios(
{
method: 'post',
url: s3PresignedUrl,
data: formData,
headers: {
"Content-Type": 'multipart/form-data; boundary=---daba-boundary---'
}
}
)
.then(res => {
console.log(res);
setUploadPercentage(100);
setTimeout(() => {
setUploadPercentage(0);
}, 1000);
})
.catch(err => {
console.log(err);
if (axios.isCancel(err)) {
alert(err.message);
}
setUploadPercentage(0);
});
};
However, when try to upload the file, it return 403 error.
And if I use fetch instead of axios instead and it works, like this:
export async function putToS3(presignedUrl: string, fileObject: any) {
const requestOptions = {
method: "PUT",
headers: {
"Content-Type": fileObject.type,
},
body: fileObject,
};
//console.log(presignedUrl);
const response = await fetch(presignedUrl, requestOptions);
//console.log(response);
return await response;
}
putToS3(getPresignedUrlResponse['s3PresignedUrl'], values.selectdFile).then(
(putToS3Response) => {
console.log(putToS3Response);
Toast("Success!!", "File has been uploaded.", "success");
}
);
It seems to me that the only difference between these two is that: when using fetch the request's Content-Type header is Content-Type: audio/mpeg, but when using axios it is Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryClLJS3r5Xetv3rN7 .
How can I make it work with axios? I'm switching to axios for its ability to monitor request progress as I want to show an upload progress bar.
I followed this blog and not sure what I missed: https://bobbyhadz.com/blog/aws-s3-presigned-url-react
You are using POST in your axios. Should be PUT instead.
Also I think the content type has to match the one specified during requesting the pre-signed URL, which is audio/mpeg as you rightly pointed out.
Correspondingly, your data should be just file, instead of formData.
axios(
{
method: 'put',
url: s3PresignedUrl,
data: file,
headers: {
"Content-Type": 'audio/mpeg'
}
}
...
You didn't mark any answers as accepted so I guess you didn't solve it.
For any future viewers out there. The reason why you are getting 403 forbidden error is because your Content-Type in your server and client side are not matching. I'm assuming you set up the AWS policies correctly.
Your code in the backend should look like this:
const presignedPUTURL = s3.getSignedUrl("putObject", {
Bucket: "bucket-name",
Key: String(Date.now()),
Expires: 100,
ContentType: "image/png", // important
});
and in the front-end (assuming you are using axios):
const file = e.target.files[0]
const result = await axios.put(url, file, {
withCredentials: true,
headers: { "Content-Type": "image/png" },
});
In practical, you would normally have to send the file type to generate the pre-signed url in the POST body or whatever and then in axios you do file.type to get the file type of the uploaded file.
Check your Lambda execution role. It may be the culprit. Perhaps it does not grant enough permissions to allow PUTting files into your bucket.
URL signing is a delegation of power on behalf of the signer, which is restricted to a specified object, action... Signing does not magically grants full read/write permissions on S3, even on the specific object related to the presigned URL.
The "user" who generates the signature requires sufficient permissions to allow the actions you want to delegate through that presigned URL. In this case, this is the execution role of your Lambda function.
You can add the AmazonS3FullAccess managed policy to the execution role and see if it solves your situation. This change took me out of a blocked situation me after days of struggle. Afterwards, before going to production, restrict that rule to the specific bucket you want to allow uploads into (least privilege principle).
If you develop using SAM local emulation, those execution roles seem not to be taken into account as long as you run your functions locally; the signed links work in that context even without S3 permissions.

firebase auth rest api not returning the full body response in arduino ide

i've been stuck in a problem with firebase auth rest api in arduino ide, the following code returns code 200
String url = "https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=" + String(apiKey);
http.setTimeout(5000);
http.begin(url);
http.addHeader("Content-Type", "application/json");
String dataSent = "{\"email\":\"" + String(email) + "\",\"password\":\"" + String(pswd) + "\",\"returSecureToken\":\"true\"}";
int status = http.POST(dataSent);
Serial.println(status);
if (status <= 0)
{
Serial.printf("HTTP error: %s\n",
http.errorToString(status).c_str());
return false;
}
// Read the response.
String payload = http.getString();
Serial.println(payload);
but when i look in my serial monitor the response looks like this:
{
kind: "the kind of response",
localId: "someId",
email: "myEmail",
displayName: "myDisplayName",
idToken: "someIdToken",
registered: "someBoolean",
}
witch aparently is ok but when i try the same http request in postman the response includes also refreshToken and expiresIn
with even more investigation i found that localId from postman is about 980 characters while the localId from my arduino code is only about 680
im trying (and failing) to use the localId to authenticate a request with the firestore api and i think this difference in lenght is what's been buggingme.
could that really be the problem ?
method: "POST",
body: JSON.stringify({
email: enteredEmail,
password: enteredPassword,
returnSecureToken: true,
}),
headers: {
"Content-Type": "application/json",
},
})
NB: Make sure {returnSecureToken: true} is part of your request body

My fetch doesn't upload the JSON string, I can't see the error in my code

I'm using Slim v4 for my REST API for testing purposes.
I want to fetch a JSON Data string to my REST API for saving some events.
public async callSaveEvent(event: EventList) {
let url: string = config.basePath + "eventList/saveEventList";
console.table(JSON.stringify(event));
await fetch(url, {
method: 'POST',
mode: 'no-cors',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ event })
}).then(response => {
if (!response.ok) {
throw new Error("Something is bad");
}
}).catch(error => {
console.error("Das ist passiert!: ", error);
});
}
This is my current Code. If I use the fetch.options.mode == "cors", I recieve in Slim that this Method is not allowed. Method is OPTIONS instead of POST. Because of this I using mode == "no-cors".
$param = $req->getParsedBody();
$param_ = $param;
$resp->getBody()->write($param);
return $resp;
}
This is my Backend Code. When I try to read the parsedBody, its just empty.
If I send a request with PostMan its accept the data and I get the data in the $param variable.
Can someone find some errors? I can't find them.

Resources