I am new to Javascript and I am trying to make an API call to randommer.io using Vanilla Javascript, but it not working. I have read the documentation on Randommer but nothing same to work. I keep getting the Cross-Origin Request Blocked error. Any help how to solve this problem. Below is the code I am using to make the API call and and X-Api-Key is also valid.
window.addEventListener('DOMContentLoaded', function () {
getData()
})
const getData = async function() {
const result = await fetch(`https://randommer.io/api/Phone/Countries`, {
method: 'GET',
headers: {
"Access-Control-Allow-Origin": '*',
Accept: 'application/json',
'x-Api-Key': 'xxxxxx',
}
})
const data = await result.json()
console.log(data)
}
You could try using the cors-anywhere proxy which you could also setup yourself.
window.addEventListener('DOMContentLoaded', function () {
getData()
})
const getData = async function() {
const result = await fetch(`https://cors-anywhere.herokuapp.com/https://randommer.io/api/Phone/Countries`, {
method: 'GET',
headers: {
"Access-Control-Allow-Origin": '*',
Accept: 'application/json',
'x-Api-Key': 'XXXX',
}
})
const data = await result.json()
console.log(data)
}
https://github.com/Rob--W/cors-anywhere
This is happening because you really should be running this server side via something like Node.js since they don't allow cors but this is a workaround if you want to run it like you are.
Your server must accept cors, otherwise this call will not work.
What you can do is create a proxy as suggested to bypass its restriction.
Related
I am new to snipcart and I can’t connect to your APi, i work with Next.js and can’t find anything on the forum or the docs releated to my problem. When I make my call with getServerSideProps i get this unhandledRejectionRequest failed with status code 404. It’s seems that’s I am not authorized to connect however i put my secret API key like in the docs.
here my code:
const secret = Buffer.from(process.env.SNIPCART_API_ID).toString('base64');
const url = 'https://api.snipcart.com/api/products';
const config = {
headers: {
'Content-Type': 'application/json',
Authorization: `Basic${secret}`,
},
};
axios.get(url, config).then((result) => {
console.log(result);
}); ```
Help is welcome :grinning:
Thanks.
From the API Docs:
const secret = "YOUR_SECRET_API_KEY"
const request = await fetch('https://app.snipcart.com/api/orders', {
headers: {
'Authorization': `Basic ${btoa(secret)}`,
'Accept': 'application/json'
}
})
const result = await request.json()
So what I see are two things:
header NOT "content-type" but "Accept"
Missing space in Authorization Header. Not sure if this is relevant for template strings.
This Netlify function should run as an endpoint on example.com/.netlify/functions/github and is supposed to proxy a fetch request from my website, reach out to the GitHub API and send data back to the website.
As far as I have understood, I can use to GET data from the GitHub API without authentication. Hitting their API directly in the browser works: https://api.github.com/orgs/github/repos?per_page=2 (also works from Postman).
The data is an array of objects where each object is a repository.
There has been multiple issues the past couple of years where Netlify functions (running on AWS lambdas) have had hickups that resulted in error messages similar to mine, so I'm confused whether this is an error in my code or something weird on their side.
First, the proxy function which – according to the Netlify admin console – runs without error. In a support article Netlify requires the result returned as JSON.stringify(), so I follow that convention here:
const fetch = require('node-fetch')
const url = 'https://api.github.com/orgs/github/repos?per_page=2'
const optionsHeaders = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'Content-Type'
}
const fetchHeaders = {
'Content-Type': 'application/json',
'Host': 'api.github.com',
'Accept': 'application/vnd.github.v3+json',
'Accept-Encoding': 'gzip, deflate, br'
}
exports.handler = async (event, context) => {
if (event.httpMethod === 'OPTIONS') {
return {
'statusCode': '200',
'headers': optionsHeaders,
}
} else {
try {
const response = await fetch(url, {
method: 'GET',
headers: fetchHeaders
})
const data = await response.json()
console.log(JSON.stringify({ data }))
return {
statusCode: 200,
body: JSON.stringify({ data })
}
} catch (err) {
console.log(err)
}
}
}
Client fetch that hits https://example.com/.netlify/functions/github. URL is correct, the function is executed (verified that in the Netlify admin panel):
const repos = document.querySelectorAll('.repo')
if (repos && repos.length >= 1) {
const getRepos = async (url) => {
try {
const response = await fetch(url, {
method: "GET",
mode: "no-cors"
})
const res = await response.text()
// assuming res is now _text_ as per `JSON.stringify` but neither
// that nor `.json()` work
console.log(res[0].name)
return res[0].name
} catch(err) {
console.log(err)
}
}
const repoName = getRepo('https://example.com/.netlify/functions/github')
repos.forEach((el) => {
el.innerText = repoName
})
}
Not 100% sure where this error message originates from, it is probably not the console.log(err) although it displays in the browser console, because the error code is 502 and the error also shows up directly in the response body in Postman.
error decoding lambda response: error decoding lambda response: json: cannot unmarshal
string into Go value of type struct { StatusCode int "json:\"statusCode\""; Headers
map[string]interface {} "json:\"headers\""; MultiValueHeaders map[string][]interface {}
"json:\"multiValueHeaders\""; Body string "json:\"body\""; IsBase64Encoded bool
"json:\"isBase64Encoded,omitempty\""; Metadata *functions.Metadata
"json:\"metadata,omitempty\"" }
Haven't found any clear information on this issue, could any of you enlighten me?
The only response that don't comply with the schema is the preflight request. From the error message, I assume you need to change:
'statusCode': '200',
to
'statusCode': 200, // StatusCode int
Even better, because there's no content, you may want to use 204 instead.
If that's still not enough, I may still want to include the body there as well, as it doesn't seem optional:
return {
'statusCode': 204,
'headers': optionsHeaders,
'body': ''
}
I'm calling an API, which is returning a body that I need to access. Calling the API via Postman works as expected. The JavaScript code is below:
async function checkIfCheater(nameToCheck) {
let testJson = {
"GameName" : nameToCheck
}
await fetch(apiGatewayCheckCheaterLocal, {
method: 'POST',
mode: 'cors',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(testJson)
}).then(response=>response.json()).then(data=>{ return data; });
}
I have tried accessing the response in multiple ways. The example here follows the accepted answer here. However, despite this, the returned value is still a Promise {<pending>} object that I cannot access the body of.
How come my object is still a promise, despite following the answer on that link, and how can I fix it?
It should be corrected as follow,
async function checkIfCheater(nameToCheck) {
let testJson = {
"GameName": nameToCheck
};
const res = await fetch(apiGatewayCheckCheaterLocal, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(testJson)
});
const data = await res.json();
return data;
}
checkIfCheater('name').then(data => console.log(data));
I seem to be having an issue with getting the expected response from a fetch call within a firebase cloud function. I'm sure it's due to my lack of knowledge on how the responses, promises, etc. work.
I'm trying to use atlassian crowd's rest api for SSO. If I use postman, I can get the desired results from the request. So I know that part of it is working.
What led me to using a cloud function is that making the same request using fetch was resulting in CORS issues from localhost. I figured if I can take the browser out of the equation, then the CORS issues would disappear. Which they have, but I'm not getting the desired response.
My cloud function looks like this:
const functions = require('firebase-functions');
const fetch = require('node-fetch');
const btoa = require('btoa');
const cors = require('cors')({origin:true});
const app_name = "app_name";
const app_pass = "app_password";
exports.crowdAuthentication = functions.https.onRequest((request, response)=>
{
cors(request, response, () =>{
let _uri = "https://my.server.uri/crowd/rest/usermanagement/1/session";
let _headers = {
'Content-Type':'application/json',
'Authorization':`Basic ${btoa(`${app_name}:${app_pass}`)}`
}
let _body = {
username: request.body.username,
password: request.body.password
}
const result = fetch(_uri, {
method: 'POST',
headers: _headers,
body: JSON.stringify(_body),
credentials: 'include'
})
response.send(result);
})
})
I'm then making the call in my application using fetch to the firebase endpoint and passing the username/password:
fetch('https://my.firebase.endpoint/functionName',{
method: 'POST',
body: JSON.stringify({username:"myusername",password:"mypassword"}),
headers: {
'Content-Type':'application/json'
}
})
// get the json from the readable stream
.then((res)=>{return res.json();})
// log the response - {size:0, timeout:0}
.then((res)=>
{
console.log('response: ',res)
})
.catch(err=>
{
console.log('error: ',err)
})
Thanks for looking.
Edit of May 2020
Note that request-promise is deprecated and I recommend to use axios.
Update following our discussion in the comments below
It appears that it doesn't work with the node-fetch library and that you should use another library like request-promise.
Therefore you should adapt your code as follows:
//......
var rp = require('request-promise');
exports.crowdAuthentication = functions.https.onRequest((request, response) => {
cors(request, response, () => {
let _uri = "https://my.server.uri/crowd/rest/usermanagement/1/session";
let _headers = {
'Content-Type': 'application/json',
'Authorization': `Basic ${btoa(`${app_name}:${app_pass}`)}`
}
let _body = {
username: request.body.username,
password: request.body.password
}
var options = {
method: 'POST',
uri: _uri,
body: _body,
headers: _headers,
json: true
};
rp(options)
.then(parsedBody => {
response.send(parsedBody);
})
.catch(err => {
response.status(500).send(err)
//.... Please refer to the following official video: https://www.youtube.com/watch?v=7IkUgCLr5oA&t=1s&list=PLl-K7zZEsYLkPZHe41m4jfAxUi0JjLgSM&index=3
});
});
});
Initial answer with node-fetch
The fetch() method is asynchronous and returns a Promise. You therefore need to wait this Promise resolves before sending back the response, as follows:
exports.crowdAuthentication = functions.https.onRequest((request, response)=>
{
cors(request, response, () =>{
let _uri = "https://my.server.uri/crowd/rest/usermanagement/1/session";
let _headers = {
'Content-Type':'application/json',
'Authorization':`Basic ${btoa(`${app_name}:${app_pass}`)}`
}
let _body = {
username: request.body.username,
password: request.body.password
}
fetch(_uri, {
method: 'POST',
headers: _headers,
body: JSON.stringify(_body),
credentials: 'include'
})
.then(res => {
res.json()
})
.then(json => {
response.send(json);
}
.catch(error => {
//.... Please refer to the following official video: https://www.youtube.com/watch?v=7IkUgCLr5oA&t=1s&list=PLl-K7zZEsYLkPZHe41m4jfAxUi0JjLgSM&index=3
});
})
})
In addition, note that you need to be on the "Flame" or "Blaze" pricing plan.
As a matter of fact, the free "Spark" plan "allows outbound network requests only to Google-owned services". See https://firebase.google.com/pricing/ (hover your mouse on the question mark situated after the "Cloud Functions" title)
React JSX project.
I'm trying to execute await fetch GET request with number of params, fails with Uncaught SyntaxError: Unexpected identifier error.
While executing the same request with Postman, it works fine.
Some syntax issue I have. What am I doing wrong?
First of all, I'm initializing the uri to some proper value.
Secondly, I'm preparing the GET options:
var options = (payload) => {
return {
method: 'GET',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
param: JSON.stringify(payload) //payload is {domainName: "idoidoido.info"}
};
};
Then, await fetch:
const response = await fetch(uri, options(param));
And, it fails with Uncaught SyntaxError: Unexpected identifier error...
I'm assuming the second parameter of fetch takes an object, but your options is a function, which must be called with the payload, so I should think your code should be
const response = await fetch(uri, options(somePayload));
Well, first of all, I hope you're using a transpiler like BabelJS, otherwise this would would fail on like 99% of all targets at present.
Your code looks fine. Since fetch returns a Promise, await can deal with it. But you have to make sure that your await statement always is located within an async function declaration. Otherwise an error is thrown at you.
So make sure your calling line has a structure like
async function getData( uri, options ) {
const response = await fetch(uri, options);
}
Succeded to solve this. Looks like query params can't be part of fetch GET request.
Solved this by preparing the request URL beforehand with URI.js.
So, the option:
const options = () => {
return {
method: 'GET',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
credentials: 'same-origin'
};
};
Then, await fetch:
const URI = require('urijs');
const request = new URI(uri).addSearch(params).toString();
const response = await fetch(uri, options());
The addSearch(params) appending the params nicely to the url:
URI("?hello=world")
.addSearch("hello", "mars")
// -> ?hello=world&hello=mars
.addSearch({ foo: ["bar", "baz"] })
// -> ?hello=world&hello=mars&foo=bar&foo=baz