I'm trying to return some data from an API using the Fetch method, but I'm getting a 400 error. I'm probably missing something obvious, but I've been at this for so long I probably can't see the wood for the trees.
<script type="text/javascript">
function getJSON() {
const API = 'https://API-URL-ENDPOINT';
const QUERY = 'sample-query';
const A_KEY = '{API Key}';
const A_SEC = '{API Secret}';
let headers = new Headers();
headers.append('Authorization', 'Basic ' + USERNAME + ":" + PASSWORD);
{/* Fetch Method Here */}
fetch(API, {method: 'GET', headers: headers })
.then(response => response.json())
.then(json => console.log(json));
}
function parseJSON(response) {
return response.json()
}
</script>
If anyone can offer any hints, that would be great.
As written in the docs for the Authorization header, you need to encode it in base64.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization
So try headers.append('Authorization', 'Basic ' + btoa( USERNAME + ":" + PASSWORD ));
Related
I can't find to much documentation regarding the mjml API. But when I make the following call it seems my headers aren't correct
const url = "https://api.mjml.io/v1/render";
const options = {
body:'<mjml><mj-body><mj-container><mj-section><mj-column><mj-text>Hello World</mj-text></mj-column></mj-section></mj-container></mj-body></mjml>',
headers: {
'Authorization': 'Basic ' + btoa('APPLICATION-ID:SECRET-KEY')
},
method: "POST"
};
fetch(url, options)
.then( res => res.json() )
.then( data => console.log(data) );
I'm trying to make a http request based on the documentation at https://developer.spotify.com/documentation/general/guides/authorization-guide/#client-credentials-flow Client Credentials Flow.
I've written
const BASE_URL = 'https://accounts.spotify.com/api/token';
fetch(BASE_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Basic ' + base64(clientID) + ':' + base64(clientSecret)
},
body: JSON.stringify({'grant_type:client_credentials'})
})
Does this follow what it says to do? I'm confused how to write the body of the post request.
What I ended up doing which works:
async authorize(){
let myHeaders = new Headers();
myHeaders.append("Authorization", `Basic ${my_clientID:clientSecret}`);
myHeaders.append("Content-Type", "application/x-www-form-urlencoded");
var urlencoded = new URLSearchParams();
urlencoded.append("grant_type", "client_credentials");
const requestOptions = {
method: 'POST',
headers: myHeaders,
body: urlencoded,
redirect: 'follow'
}
let res = await fetch("https://accounts.spotify.com/api/token", requestOptions);
res = await res.json();
return res.access_token;
}
async search(){
const access_token = await this.authorize();
this.setState({access_token});
const BASE_URL = 'https://api.spotify.com/v1/search';
let FETCH_URL = `${BASE_URL}?q=${this.state.query}&type=artist&limit=1`;
const ALBUM_URL = 'https://api.spotify.com/v1/artists';
let myHeaders = new Headers();
myHeaders.append("Authorization", `Bearer ${access_token}`);
const requestOptions = {
method: 'GET',
headers: myHeaders
}
let res = await fetch(FETCH_URL, requestOptions);
res = await res.json();
console.log("ARTIST", res);
}
From the link you have shared, the client credential flow is a client (server-side) that makes a request to the spotify API server. Thus, it is a server-to-server authentication flow (not authorization). You are using the fecth API which is client-side so that means that your implementation should be server-side. If you are using a node.js runtime server-side framework, just look up the http.request API to make a request server-side.
For example, this would be a pure node.js implementation:
const options = {
hostname: 'https://accounts.spotify.com/api/token',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Basic ' + base64(clientID) + ':' + base64(clientSecret)
}
};
const req = http.request(options, (res) => {
res.setEncoding('utf8');
// process the data bit by bit or in chunks...
res.on('data', (chunk) => {});
// ...and do something with it when there is no more data in response
res.on('end', () => {
console.log('No more data in response.');
});
});
// handle the error explicitly
req.on('error', (e) => {
console.error(`problem with request: ${e.message}`);
});
req.end();
For me, I'm not sure if this is the case for anyone else, but the spotify api was refusing base64(clientID) + ":" + base64(clientKey), but accepting base64(clientID + ":" + clientKey)
backend server API send me a number and i have to fetch it in a response in react front end. But i am not able to read it by using response.json() or response.body(). Can anyone help me how to read the response as a number for fetch repsonse.
let url = "API URl"
var requestOptions = {
method: 'GET',
redirect: 'follow'
};
fetch(url + new URLSearchParams({selectedReportName: this.state.selectedRepor}), requestOptions)
.then( response => response.json())
.then(data =>{
console.log ("Data " + data)} )
let url = "API URl"
var requestOptions = {
method: 'GET',
redirect: 'follow'
};
fetch(url + new URLSearchParams({selectedReportName: this.state.selectedRepor}), requestOptions)
.then( response => response.json())
.then(data =>{
console.log ("Data " + data)} )
.catch(err => console.log("err:", err));
Try the above-mentioned code, It'll give you an exact error if we're not getting 200 response from the server or something is not working.
I trying to get a download of a json file from an API.
To do that, I need to call 3 endpoints.
http://url.com/export
it returns a json: {"exportLoading":true,"file":"export-20190618-183316.json"}
After that I should call the second endpoint and check the status of this exportation:
http://url.com/export/status
it returns true or false (while server is processing, this endpoint returns true. When it returns false the file is done to make a download.)
So, if the status === false, I can call the last endpoint
http://url.com/download/file_name (I make this request passing the file name - returned from the first request - to download the file.
My question is, how can I check if the second endpoint returns false to make the last request and download the file?
I just did it until the second endpoint.
app.get('/export', function (req, res, next) {
global.fetch = fetch
global.Headers = fetch.Headers;
const headers = new Headers();
const username = 'user';
const password = 'pass';
const URL = 'http://url.com/export'
headers.set('Authorization', 'Basic ' + base64.encode(username + ":" + password));
fetch(URL, {
method: 'GET',
headers: headers,
})
.then(res => res.json())
.then(json => {
fetch("http://url.com/exportl/status", {
method: 'GET',
headers: headers,
}).then(result => ...)
})
.catch(function (error) {
console.log(error)
})
});
You could use a while loop that will call the endpoint until the condition is met:
app.get('/export', async function(req, res, next) {
global.fetch = fetch
global.Headers = fetch.Headers;
const headers = new Headers();
const username = 'user';
const password = 'pass';
const URL = 'http://url.com/export'
headers.set('Authorization', 'Basic ' + base64.encode(username + ":" + password));
fetch(URL, {
method: 'GET',
headers: headers,
}).then(r => r.json)
.then(data => {
// use data here
var status = false
while (!status) {
status = await checkStatus()
}
// third call
})
});
function checkStatus() {
return fetch("http://url.com/exportl/status", {
method: 'GET',
headers: headers,
}).then(r => r.json)
}
Note, I do not know the response from the status, you will have to change the code to accommodate the response.
I want to write a simple basic authentication with fetch, but I keep getting a 401 error. It would be awesome if someone tells me what's wrong with the code:
let base64 = require('base-64');
let url = 'http://eu.httpbin.org/basic-auth/user/passwd';
let username = 'user';
let password = 'passwd';
let headers = new Headers();
//headers.append('Content-Type', 'text/json');
headers.append('Authorization', 'Basic' + base64.encode(username + ":" + password));
fetch(url, {method:'GET',
headers: headers,
//credentials: 'user:passwd'
})
.then(response => response.json())
.then(json => console.log(json));
//.done();
A solution without dependencies.
Node
headers.set('Authorization', 'Basic ' + Buffer.from(username + ":" + password).toString('base64'));
Browser
headers.set('Authorization', 'Basic ' + btoa(username + ":" + password));
You are missing a space between Basic and the encoded username and password.
headers.set('Authorization', 'Basic ' + base64.encode(username + ":" + password));
A simple example for copy-pasting into Chrome console:
fetch('https://example.com/path', {method:'GET',
headers: {'Authorization': 'Basic ' + btoa('login:password')}})
.then(response => response.json())
.then(json => console.log(json));
or with await:
let response = await fetch('https://example.com/path', {method:'GET',
headers: {'Authorization': 'Basic ' + btoa('login:password')}});
let data = await response.json();
console.log(data);
In pure JavaScript you can also use btoa instead of base64.encode():
headers.set('Authorization', 'Basic ' + btoa(username + ":" + password));
Note that this will only work with ASCII characters.
If you have to handle different encodings, see the linked btoa documentation.
If you have a backend server asking for the Basic Auth credentials before the app then this is sufficient, it will re-use that then:
fetch(url, {
credentials: 'include',
}).then(...);
NODE USERS (REACT,EXPRESS) FOLLOW THESE STEPS
npm install base-64 --save
import { encode } from "base-64";
const response = await fetch(URL, {
method: 'post',
headers: new Headers({
'Authorization': 'Basic ' + encode(username + ":" + password),
'Content-Type': 'application/json'
}),
body: JSON.stringify({
"PassengerMobile": "xxxxxxxxxxxx",
"Password": "xxxxxxx"
})
});
const posts = await response.json();
Don't forget to define this whole function as async
get request with authorization for React Native Mobile application, i have spent more time searching for these lines inside fetch
var base64 = require("base-64"); // install it before use from npm i base-64
const uname = "some username goes here";
const pword = "some password goes here";
const getMovies = async () => {
try {
const response = await fetch(
"API URL goes here",
{
headers: {
Authorization: "Basic " + base64.encode(uname + ":" + pword),
},
}
);
data = await response.json();
setData(data);
console.log(data);
// console.log(data.name);
return data;
} catch (error) {
console.error(error);
} finally {
setLoading(false);
}
};
useEffect(() => {
getMovies();
}, []);
// other code
// inside return
<FlatList
keyExtractor={(item) => item.id}
data={data}
renderItem={({ item }) => (
<View style={styles.text_container}>
<Text>{item.name}</Text>
<Text>{item.images[0].name}</Text>
<Text>{item.images[0].src}</Text>
</View>
)}
/>
I'll share a code which has Basic Auth Header form data request body,
let username = 'test-name';
let password = 'EbQZB37gbS2yEsfs';
let formdata = new FormData();
let headers = new Headers();
formdata.append('grant_type','password');
formdata.append('username','testname');
formdata.append('password','qawsedrf');
headers.append('Authorization', 'Basic ' + base64.encode(username + ":" + password));
fetch('https://www.example.com/token.php', {
method: 'POST',
headers: headers,
body: formdata
}).then((response) => response.json())
.then((responseJson) => {
console.log(responseJson);
this.setState({
data: responseJson
})
})
.catch((error) => {
console.error(error);
});
This is not directly related to the initial issue, but probably will help somebody.
I faced same issue when was trying to send similar request using domain account. So mine issue was in not escaped character in login name.
Bad example:
'ABC\username'
Good example:
'ABC\\username'