Cors with api in react [duplicate] - reactjs

This question already has answers here:
No 'Access-Control-Allow-Origin' header is present on the requested resource—when trying to get data from a REST API
(26 answers)
Closed 3 months ago.
I'm making a simple currency converter, and I can't overcome the error:
picture with error
Here is a part of code:
try {
const { data } = await axios.get(
'https://api.privatbank.ua/p24api/pubinfo?json&exchange&coursid=5',
{
method: 'POST',
mode: 'no-cors',
headers: {
Accept: 'application/json',
WithCredentials: true,
'Access-Control-Allow-Origin': 'http://localhost:3000/',
'Content-Type': 'application/json; charset=UTF-8',
'Access-Control-Allow-Methods': 'OPTIONS,GET,POST,PUT,DELETE',
'Access-Control-Allow-Headers':
'Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With',
Authorization: '',
},
withCredentials: true,
credentials: 'same-origin',
}
)
data.push({ ccy: 'UAH', buy: '1', sale: '1' })
data.splice(2, 1)
return data
} catch (error) {
alert(error)
}
}
Help please :)
tried many solutions from google but to no avail...

The problem can be solved by using proxies
The proxy I have used in this example is allOrigins which is a free and opensource proxy
Using Axios, (You can change url with whatevery url you want)
try {
const url = "https://api.privatbank.ua/p24api/pubinfo?json&exchange&coursid=5";
const { data } = await axios.get(
`https://api.allorigins.win/raw?url=${encodeURIComponent(url)}`
);
data.push({ ccy: "UAH", buy: "1", sale: "1" });
data.splice(2, 1);
return data;
} catch (error) {
alert(error);
}
Using Fetch api, (You can change url with whatevery url you want)
try {
const url = "https://api.privatbank.ua/p24api/pubinfo?json&exchange&coursid=5";
const data = await fetch(
`https://api.allorigins.win/raw?url=${encodeURIComponent(url)}`
)
.then((response) => response.json())
.then((data) => data);
data.push({ ccy: "UAH", buy: "1", sale: "1" });
data.splice(2, 1);
return data;
} catch (error) {
alert(error);
}

Related

NextJs API endpoint returning response object without 'message' or 'body'

I have a NextJs app where
Users could fill in some input fields and submit the form (Formik Form).
Form submission is handled by the API route to do some calculations (I can do this on the client side but it's required to do it on the server side in this case)
Everything is working fine except for the response object that is returned by the API endpoint to the client
/pages/api/calculation.js
const handler = (req, res) => {
// deny the request if not post method
req.method !== 'POST' &&
res.status('403').json({
status: 403,
message: 'Forbidden',
});
// all the logic goes here
// return the response
// also tried a few others like (res.status(200).json({ message: 'Hello from Next.js!' });
return res.send({ status: 200, message: 'Hello from Next.js!' });
};
export default handler;
/pages/index.jsx
Inside Formik's onSubmit prop
fetch('/api/mbti/result', {
method: 'POST',
headers: {
Accept: 'application/json, text/plain, */*',
'Content-Type': 'application/json',
},
body: JSON.stringify(values),
}).then((res) => {
console.log(res);
if (res.status === 200) {
resetForm(); // reset form
}
});
This is the response object
body: (...)
bodyUsed: false
headers: Headers {}
ok: true
redirected: false
status: 200
statusText: "OK"
type: "basic"
url: "http://localhost:3000/api/calculation"
On the client side, I would like to get access to the 'message' inside the body from the response object that is returned by the API. Currently, the body inside the response object is only (...) as you could see above.
Since you're using fetch, you'll want to convert the Response body to json. By default, the Response body is a Readable Stream.
You can use Promise thenables:
fetch('/api/mbti/result', {
method: 'POST',
headers: {
Accept: 'application/json, text/plain, */*',
'Content-Type': 'application/json',
},
body: JSON.stringify(values),
}).then(res => {
if (!res.ok) {
res.text().then(err => throw new Error(err));
}
res.json().then(data => {
console.log('API response data', data);
resetForm(); // reset form
}).catch(err => throw new Error(err));
}).catch(err => console.error(err));
Or, I'd recommend that you use async/await because it's a bit cleaner:
const onSubmit = handleSubmit(async values => {
try {
const res = await fetch('/api/mbti/result', {
method: 'POST',
headers: {
Accept: 'application/json, text/plain, */*',
'Content-Type': 'application/json',
},
body: JSON.stringify(values),
});
if (!res.ok) {
const error = await res.text();
throw new Error(error);
}
const data = await res.json();
console.log("API response data", data);
resetForm();
} catch(err) {
console.error(err);
}
});
On a related note, you have a bug in your API endpoint where it'll try to send headers after they've already been sent:
const handler = (req, res) => {
// deny the request if not post method
// if you don't return here, then it'll continue down the call stack and try to send a valid response as well
if(req.method !== 'POST')
return res.status('403').json({
status: 403,
message: 'Forbidden',
});
// return the valid response
return res.send({ status: 200, message: 'Hello from Next.js!' });
};
export default handler;

How to handle authorization headers on API call in React?

I'm trying to make a GET request to retrieve Total balance for a payment summary. I get a 401 unauthorized error on the console.
const getPay = () => {
Axios({
method: "GET",
url: `apiEndpoint/${variable}`,
headers: {
'Content-Type': 'application/json',
'x-access-token': "Available upon request"
}
})
.then((response) => {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
useEffect(() => {
getPay()
}, [])
The API docs states "Every request to any of the endpoints must contain the headers." The headers above were stated but I get an error 401(Unauthorized). please how do I go about this?
Just add Authorization in your headers
const getPay = () => {
Axios({
method: "GET",
url: `apiEndpoint/${variable}`,
headers: {
'Content-Type': 'application/json',
'x-access-token': "Available upon request",
Authorization: `Bearer YOUR_TOKEN`
}
})
.then((response) => {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
useEffect(() => {
getPay()
}, [])
Also, It is better to implement axios interceptors so that you dont have to pass headers in each call
// Request interceptor
API.interceptors.request.use(
async axiosConfig => {
const token = await getToken()
if (token && axiosConfig.headers) {
axiosConfig.headers.Authorization = `Bearer ${token}`
}
return axiosConfig
},
error => Promise.reject(error),
)

Simple get from soundcloud playlist works well in postmann. But Fetch returns status 200 yet no response

So I'm using the GET method with Fetch to get some data from soundcloud.
In postman, it works fine. But when i use Fetch I get Status:200 but:
'Failed to load response data: No data found for resource with given identifier'
const soundcloudUrl = 'https://api-v2.soundcloud.com/users/473442966/tracks?client_id=IPz5SBL08EN3FyBabMnvLpb0AAKYGtrd&limit=2&offset=0&linked_partitioning=1&app_version=1645088469&app_locale=en';
/**
* #param {string} url=''
* #param {string} method
*/
async function getData(url = '', method) {
console.log(url);
return fetch(url, {
method, // *GET, POST, PUT, DELETE, etc.
mode: 'no-cors', // no-cors, cors, *same-origin
cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
// credentials: 'same-origin', // include, *same-origin, omit
headers: {
'Content-Type': 'text/plain',
// "Content-Type": "application/x-www-form-urlencoded",
},
redirect: 'follow', // manual, *follow, error
referrer: 'no-referrer', // no-referrer, *client
body: JSON.stringify(), // body data type must match "Content-Type" header
})
.then((response) => {
console.log(response.text());
return response.text();
})
.then((data) => {
console.log(data);
data ? JSON.parse(data) : {};
})
.catch((error) => {
console.log(error); // reject(error);
});
}
/**
* #param {object} data
*/
export async function getPodcaststreams(data) {
const url = new URL('', soundcloudUrl);
let response;
try {
response = await getData(url.href, 'GET');
} catch (e) {
return (e);
}
console.log(response);
}
Here's my Network response:
network response
Here's the response I get in Postman:
postman response
Also, if I click the url, I can see the data.
Any ideas good people?
Best regards.
Two things I can see that you are doing wrong here. First is calling response.text() twice. The response can only be read once so
console.log(response.text());
return response.text();
will not be able to read response as it has been read already. This is why you are getting an undefined response when you try and parse the data.
Secondly, you don't need to call JSON.parse(data) as the fetch api includes a response.json() method which will parse the response as json. Your getData should look something like this:
async function getData(url = '', method) {
return fetch(url, {
method,
mode: 'no-cors',
cache: 'no-cache',
headers: {
'Content-Type': 'text/plain'
},
redirect: 'follow',
referrer: 'no-referrer',
body: JSON.stringify()
})
.then((response) => {
return response.json();
})
.catch((error) => {
console.log(error); // reject(error);
});
}

How to send body data and headers with axios get request?

I've tried
axios.get(url, {headers:{},data:{}})
But it doesn't work with this.
You should refer to https://github.com/axios/axios#request-config
Check the section for data and header.
As far as I know you can't send body data with GET request. With get you can have only Headers. Just simply change to POST and then you can do something like this :
const bodyParameters = {
key: "value",
};
const config = {
headers: { Authorization: `Bearer ${userToken}` },
};
axios.post("http://localhost:5000/user", bodyParameters, config)
.then((res)=> {
console.log(res)
})
.catch((err) => console.log(err));
};
or if you want to send headers with GET request
axios.get('/user', {
params: {
ID: 12345
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
})
.then(function () {
// always executed
});
// data is the data to be sent as the request body
// Only applicable for request methods 'PUT', 'POST', 'DELETE , and 'PATCH'
https://stackoverflow.com/a/54008789
yeah, it's true it doesn't work to send body in Axios get even if it works in the postman or the backend.
You can try this:
const getData = async () => {
try {
const response = await axios.post(`https://jsonplaceholder.typicode.com/posts`, {
method: 'POST',
body: JSON.stringify({
id: id,
title: 'title is here',
body: 'body is here',
userId: 1
}),
headers: {
"Content-type": "application/json; charset=UTF-8"
}
})
.then(response => response.json())
.then(json => console.log(json));
console.warn(response.data);
} catch (error) {
console.warn(error);
}
}
You can send data in a get request by using the config object and the params option of the config object. This is a workaround and it works, but on the server the data sent is available as request.query not as request.body. Based on the example below you would access your params data on your server using request.query.user_id. It should be noted that using this method will also append the params to your request url which could have unintended consequences based on your specific situation. For example, the url for the request below would be sent as example.com?user_id=1234. You can read more about the axios request config here.
axios.get(
'example.com/',
{
params: { user_id: 1234 },
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json',
},
},
);

axios.post returns bad request of 400 React Native

I'm getting my token from an API but unfortunately my API is returning 400 bad request. I've already checked my api via Postman and it's working fine there. Kindly let me know solution or any mistake.
async componentWillMount(){
axios.post('http://api.myapiurl.com/token', {
grant_type: 'PASSWORD',
username: 'MY_USERNAME',
password: 'MY_PASSWORD'
}, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
}
}).then(response => {
console.log(response.data)
}).catch(err => console.log("api Erorr: ", err.message))
}
error in response below
Request failed with status code 400
- node_modules\axios\lib\core\createError.js:16:24 in createError
- node_modules\axios\lib\core\settle.js:18:6 in settle
- ... 10 more stack frames from framework internals
It is Solved by using QueryString.stringify(). I just pass the body into QueryString.stringify() like below:
axios.post('http://api.apiurl.com/token', QueryString.stringify({
grant_type: 'MY_GRANT_TYPE',
username: 'MY_USERNAME',
password: 'MY_PASSWORD'
}), {
headers: {
"Content-Type": "application/x-www-form-urlencoded",
}
}).then(response => {
console.log(response.data)
}).catch(err => console.log("api Erorr: ", err.response))
From what I can see you are sending json data, but your Content-Type header is set to application/x-www-form-urlencoded; charset=UTF-8. if your api is expecting json then it should be application/json.
try using fetch instead, might be some axios bug, you dont need to add any libraries, here is an example:
fetch("http://api.myapiurl.com/token", {
method: "POST", // *GET, POST, PUT, DELETE, etc.
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
grant_type: "PASSWORD",
username: "MY_USERNAME",
password: "MY_PASSWORD"
})
})
.then(res => {
res.json();
})
.then(data => console.log(data)) // ur data is here
.catch(err => console.log("api Erorr: ", err));
First install the package axios from the url https://www.npmjs.com/package/react-native-axios
Then create two service for handling get and post request so that you can reuse them
GetService.js
import axios from 'axios';
let constant = {
baseurl:'https://www.sampleurl.com/'
};
let config = {
headers: {
'Content-Type': 'multipart/form-data',
'Accept': 'application/json'
}
};
export const GetService = (data,Path,jwtKey) => {
if(jwtKey != ''){
axios.defaults.headers.common['Authorization'] = 'Bearer '+jwtKey;
}
try{
return axios.get(
constant.baseUrl+'api/'+Path,
data,
config
);
}catch(error){
console.warn(error);
}
}
PostService.js
import axios from 'axios';
let constant = {
baseurl:'https://www.sampleurl.com/'
};
let config = {
headers: {
'Content-Type': 'multipart/form-data',
'Accept': 'application/json'
}
};
export const PostService = (data,Path,jwtKey) => {
if(jwtKey != ''){
axios.defaults.headers.common['Authorization'] = 'Bearer '+jwtKey;
}
try{
return axios.post(
constant.baseUrl+'api/'+Path,
data,
config
);
}catch(error){
console.warn(error);
}
}
Sample code for using get and post services is given below
import { PostService } from './PostService';
import { GetService } from './GetService';
let uploadData = new FormData();
uploadData.append('key1', this.state.value1);
uploadData.append('key2', this.state.value2);
//uploadData.append('uploads', { type: data.mime, uri: data.path, name: "samples" });
let jwtKey = ''; // Authentication key can be added here
PostService(uploadData, 'postUser.php', jwtKey).then((resp) => {
this.setState({ uploading: false });
// resp.data will contain json data from server
}).catch(err => {
// handle error here
});
GetService({}, 'getUser.php?uid='+uid, jwtKey).then((resp) => {
// resp.data will contain json data from server
}).catch(err => {
// handle error here
});
Reference from one of my another post Post action API with object parameter within the URL
If you have any doubts, feel free to know

Resources