Bad Request on accessing Firebase dynamic-links using REST API (using JS) - javascript

I'm trying to implement a simple URL shortener using firebase dynamic links via the REST API.
I prepared a simple async JS function for testing (since I don't have a billing account to make external egress calls in cloud functions).
Below is the code:
async function fetcher(keyAPI,tempURL) {
let reqURL=`https://firebasedynamiclinks.googleapis.com/v1/shortLinks?key=${keyAPI}`;
let parameters = {
method : "POST",
headers: {
'Content-Type': 'application/json'
},
body : JSON.stringify({
"longDynamicLink": tempURL,
"suffix": {
"option": "SHORT"
}
})
};
await fetch(reqURL,parameters)
.then(res => console.log(res))
.catch(err => console.log(err));
}
I'm recieving a bad request as the response:
Response {
type: "cors", "https://firebasedynamiclinks.googleapis.com/v1/shortLinks?key=[MY_WEB_API_KEY_HERE]",
redirected: true,
status: 400,
ok: false,
statusText: "Bad Request",
headers: Headers,
body: ReadableStream,
bodyUsed: false
}
I need help to debug it.

Try the following after creating a prefix link URL in the firebase console since it is required as a parameter:
let reqURL=`https://firebasedynamiclinks.googleapis.com/v1/shortLinks?key=<API_KEY_HERE>`;
let parameters = {
method : "POST",
headers: {
'Content-Type': 'application/json'
},
body : JSON.stringify({
"dynamicLinkInfo": {
"domainUriPrefix": "[PREFIX_URL]",
"link": "[YOUR_LINK]",
},
"suffix": {
"option": "SHORT"
}
})
};
// Get response since it returns pending promise above
return await fetch(reqURL,parameters)
.then(res => res.json())
.catch(err => err);
}
// Fetch from Promise
sURL.then(res => {
console.log(res);
return res;
});

My previous answer was deleted, I don't know why, but its ok
Deleted Post IMG
I faced this problem earlier and some research on it. And it was working. So I took my all code, cleaned it up, and published it on Github, so this doubt can go.
So, Some comments asked How to use this, So here is the answer
You have to add lib from the CDN or self host it, its better to customize the code by yourself for your needs. CDN Link - https://fdl.js.org/src/links.js
Now when you have added the lib, try to call it with this function.
This returns you the shortlink
makefdl(key, st, si, sd, domain, link);
Expression Docs
And You get the shortlink back...
Note: You have to wait for the API to reply, so make a await call, like this
async function links(){
var slink = await makefdl(key, st, si, sd, domain, link);
if(slink != null){
console.log(slink);
// do something here with the shortlink
}
}
<script src="https://fdl.js.org/src/links.js"></script>
If you have any questions then please write down in the comments. I will be happy to answer. :)
For more info about FDljs, visit FDL.js Official Site

Related

How can I update the message body using gmail API in javascript

I have got the message body. Now I want to update it according to my needs. I am using this login/code. but it says 400 error. I think issue is in body parameter of the request. Would you please help me there?
var token = localStorage.getItem("accessToken");
var messageId = "18514426e2b99017";
async function updateMessageBody() {
var updatedBody = "Hello,\n\nThis is the UPDATED message body.\n\nBest regards,\nJohn";
const API_KEY = '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-CXIk';
const headers = {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
};
const response = await fetch(`https://gmail.googleapis.com/gmail/v1/users/me/messages/18514426e2b99017/modify?key=['API_KEY']`, {
method: 'POST',
headers: headers,
body: JSON.stringify({
raw: window.btoa(unescape(encodeURIComponent(updatedBody)))
})
});
if (!response.ok) {
// throw new Error(`Request failed with status code ${response.status}`);
}
return await response.json();
}
updateMessageBody()
.then(response => {
console.log('Message body updated successfully:', response);
})
.catch(error => {
});
Checking the documentation, it states that a message body can't be altered once it has been created, meaning that once you have already created an email this message can't be changed. You can verify this here.
You can instead update a message draft which is possibly what you are trying to do, however using the endpoint you have in your code this won't be possible and will lead to the error message you are getting, try using instead the users.draft.update method that allows you to modify the content of the draft sitting in your mailbox. Please note as well that using the method users.messages does not have any update method as they only have the modify one's, those methods can only update the labels though so please be aware of that.

Fetch vs Axios review?

I'm currently learning how to use axios and fetch api. I'm trying to make a request using a fetch api like this:
let response = await fetch('https://online.yoco.com/v1/charges/', {
method: 'POST',
headers: {
'X-Auth-Secret-Key': process.env.SECRET_KEY,
},
body: {
token: paymentToken,
amountInCents: 2799,
currency: 'ZAR'
}
});
let responseData = await response.json()
And an axios post request like this:
axios.post(
'https://online.yoco.com/v1/charges/',
{
token: 'tok_test_DjaqoUgmzwYkwesr3euMxyUV4g',
amountInCents: 2799,
currency: 'ZAR',
},
{
headers: {
'X-Auth-Secret-Key': SECRET_KEY,
},
},
)
.then(res => {
//code
})
.catch(error => {
// handle errors
})
Is the request the same or not?
Cause the fetch returns an error
No, those aren't the same, in two ways:
If you look at MDN's documentation for fetch, you'll see that it says this about body:
body
Any body that you want to add to your request: this can be a Blob, an ArrayBuffer, a TypedArray, a DataView, a FormData, a URLSearchParams, string object or literal, or a ReadableStream object. This latest possibility is still experimental; check the compatibility information to verify you can use it. Note that a request using the GET or HEAD method cannot have a body.
Notice that a plain object is not on that list.
You're not checking for HTTP errors. This is unfortunately a footgun in the fetch API (I wrote about it here): It only rejects its promise on network errors, not HTTP errors like 404.
I'm going to assume that your API accepts JSON. If so, you need to include the Content-Type header and call JSON.stringify:
let response = await fetch("https://online.yoco.com/v1/charges/", {
method: "POST",
headers: {
"X-Auth-Secret-Key": process.env.SECRET_KEY,
"Content-Type": "application/json", // ***
},
body: JSON.stringify({ // ***
token: paymentToken,
amountInCents: 2799,
currency: "ZAR",
}), // ***
});
if (!response.ok) { // ***
throw new Error(`HTTP error ${response.status}`); // ***
} // ***
let responseData = await response.json();

cross origin for amazon lambda function from localhost in gatsby site

I have the following code which works when I run it as a local serverless function with netlify dev, but I need it to run cross origin from a dev server to the hosted server function. I put the function in a aws lambda function but I am getting a cross origin blocked error on my https:dev.website.com, I thought I have the correct headers in the return object so not sure why I am getting a cross origin error.
Any help would be great
const sanityClient = require("#sanity/client");
const client = sanityClient({
projectId: "random-id",
dataset: "production",
useCdn: true,
});
exports.lambdaHandler = async (event, context) => {
var body = JSON.parse(event.body);
//console.log(body.price_id)
try {
const checkPriceId = async (test) => {
const query = `*[_type == "products" && price_id == "${body.price_id}"]`;
const documents = await client.fetch(query, {}); // this could throw
return documents.map((document) => document.sold);
};
var ok = checkPriceId().then((test) => {
return new Promise(function (resolve, reject) {
//console.log(test) // this will log the return value from line 7
console.log(test);
resolve(test);
});
});
var bools = await ok;
// prettier-ignore
return {
statusCode: 200,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Allow-Methods':'GET, POST, OPTION',
},
body: JSON.stringify({
sold: bools,
}),
};
} catch (err) {
return { statusCode: 500, body: err.toString() };
}
};
This is my request to the function if that helps
var fetchUrl = https://random.executue-api.aws.com/prod/sold //not exact
var fetchData = async function () {
const response = await fetch(fetchUrl, {
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
price_id: final,
}),
})
.then(res => {
return res.json()
})
.catch(error => console.log(error))
return response
}
Update:
I tried adding cors the way suggested in the answer below, but it failed seen below so I tried manually adding the method response seen after.
I still get a cross domain error. And I have changed the domain so it is now https as well. Really stuck here.
I was looking into this more, and it seems like before it does the actual post it does a cors check at the options method, so I added in the same access control headers, and deployed but did not work. Don't quite get this.
Your headers look ok to me. (note: If you mix HTTP and HTTPS you are most likely to get a mixed content error in the client). If it is ONLY a CORS issue that you are seeing in the console in the web browser, then you might not have configured the API Gateway correctly in AWS.
In AWS, go to API Gateway and you should see something like the below:
Make sure that you enable CORS and then redeploy.
UPDATE:
Just looking at a previous implementation of a lambda function I setup with AWS. The headers I declared were as follows:
headers: {
"Content-Type" : "application/json",
"Access-Control-Allow-Origin" : "*",
"Allow" : "GET, OPTIONS, POST",
"Access-Control-Allow-Methods" : "GET, OPTIONS, POST",
"Access-Control-Allow-Headers" : "*",
"Access-Control-Allow-Credentials" : true
}
Your headers look OK to me though. However, when you created the method in the API Gateway, did you select Use Proxy Lambda Integration? (see screenshot).
Your client side fetch request looks ok. For reference mine was:
const url = 'your url';
const options = {
method: 'POST',
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
};
fetch(url, options).then(res => res.json());
Unrelated to this issue, but its not advisable to mix Async/Await with .then promise chaining. But this isn't the issue you are having. Just something to note.
Check the values from your Integration Response / try setting them manually for both OPTIONS and POST (and if that works, make sure you are passing through the response correctly from the lambda).
Your POST action should only require the Access-Control-Allow-Origin header. The other two (Access-Control-Allow-Methods, Access-Control-Allow-Headers) belong in the OPTION action. See this writeup, and note the full example exchange for a preflighted request (in grey): https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#preflighted_requests

MTN MOMO API CreateAPI User - 401 Access Denied

I need you help with the MTN MOMO API...I am posting below some code I tried debugging for the entire day yesterday. The code works in Postman but the same fails to work in browser since Browsers implement CORS( Access-Control-Allow-Origin). Any guidance would be appreciated.
I was able to work around the CORS issue, now am stuck on the error ' POST https://sandbox.momodeveloper.mtn.com/v1_0/apiuser 401 (Access Denied) '. This error worries me since I have give all parameters as needed by the API call.
async function postData() {
try {
let result = await fetch(
"https://sandbox.momodeveloper.mtn.com/v1_0/apiuser",
{
method: "post",
mode: "no-cors",
headers: {
"X-Reference-Id": "9de3e973-53c8-4cc4-a8eb-25a4a9ccb5f9",
"Ocp-Apim-Subscription-Key": "15e4e92ef6914728b8414e2bb67d7357",
"Content-type": "application/json",
//'Access-Control-Allow-Origin': '*'
},
body: JSON.stringify({
providerCallbackHost: "username",
}),
}
);
console.log(result);
} catch (e) {
console.log(e);
}
}
I decided to post the KEYS since they are on sandbox and not live account(I have no live account yet).
THe full API is here...https://momodeveloper.mtn.com/

POST and GET API Request using fetch, cannot get the data

i'm trying to use this website: https://rel.ink/,
to implement a link-shortener in my webapp,
i can successfully POST a request, but what i GET back is the same object, not a shortened version.
I know it's basic stuff but i can't wrap my head around it.
The website states that i need to send more information with my GET request, but the GET requests should not contain a body yes?
Here's my code:
async function fetchNewLink() {
let newLinkJson = await postLink(input.value)
let newLink = await getShortLink(newLinkJson)
console.log(newLink)
}
function postLink(input) {
return fetch('https://rel.ink/api/links/', {
method: 'POST',
body: JSON.stringify({
url: input
}),
headers: {
"Content-type": "application/json"
}
})
.then(response => response.json())
.then(json => json)
}
function getShortLink(response) {
return fetch('https://rel.ink/api/links/' + response.hashid)
.then(result => result.json())
.then(newLink => newLink)
}
Many thanks
If what you're trying to get is the shortened version of the link, the API does not return exactly that when you make a request. However, all you need is the hashid it returns. The shortened link is the main website's url(https://rel.ink) concatenated with the hashid.
So if the API returns nJzb3n as the hashid when you make a POST request, the shortened link would be https://rel.ink/nJzb3n
I hope that helps.

Categories

Resources