api.addAsyncRequestTransform is not a function error - react-native

const api = apisauce.create({
// base URL is read from the "constructor"
baseURL,
// here are some default headers
headers: {
'Cache-Control': 'no-cache'
},
// 10 second timeout...
timeout: 10000
})
api.addAsyncRequestTransform(request => async () => {
request.headers['Authorization'] = 'Bearer ' + await AsyncStorage.getItem('#nytevibetoken');
});
throwing api.addAsyncRequestTransform is not a function error. Why? I want to fethc token from AsyncStorage and add it o header. Any suggestion?

The ability to add transformations to async requests was introduced in version 0.10.0 of apisauce.
I attempted to execute your snippet in 0.8.0 and received the same error. Once I upgraded to 0.10.0, the error went away.
Check your package.json dependencies and update apisauce if required.

Related

How to get data correctly using the Spotify API with React

I have the following problem when I request data from the Spotify API, at first I get it, but when I reload the page or try to write this state using useState, an error 400 or 401 occurs. The code I use to get the data:
`
import axios from 'axios';
const BASE_URL = 'https://api.spotify.com/v1';
export const fetchFromAPI = async (url: string, token: string) => {
const { data } = await axios.get((`${BASE_URL}/${url}`), {
method: 'GET',
headers: {
Accept: "application/json",
"Content-Type": "application/json",
Authorization: `Bearer ${token}`
},
});
return data;
}
`
Next, I use the fetchFromAPI function:
`
const { token } = useContext(Context);
const [albums, setAlbums] = useState<string[]>([]);
useEffect(() => {
fetchFromAPI('browse/new-releases', token)
.then((data) => console.log(data));
}, [token])
`
I've tried logging out of my account and back in, I've also tried other links to get data but it's always the same problem. I also checked if the token is present before requesting the data and it is
Ok, I managed to find and solve this error myself.
The error was that I didn't have a user token yet, but useEffect was already starting to receive data.
useEffect(() => {
if (token) {
fetchNewReleases();
fetchFeaturedPlaylists();
fetchCategories();
fetchRecommendations();
} else {
console.log('error');
}}, [token])
For example, this piece of code will print an error twice, and only after that I receive a token and can receive data from the API.
To be honest, I didn't know how to run useEffect only when I have a token, so I solved it in a simpler way, but I don't know if it's completely correct, I have the following condition Object.values(state).length) !== 0 and if it is true, only then will I display the data from the API

Unexpected behaviour of payment_intent api with GET and POST method

I am using the payment_intent API to generate payment intent for payment sheet initialization.
As per the document, payment_intent is the POST method. Showing different errors in android and iOS.
https://stripe.com/docs/api/payment_intents/create
Note:- It's working in postman not working on mobile.
Case 1 Android
It is not working with the POST method. It worked with the GET method this is weird.
Case 2 iOS
It is not working with the GET and POST methods both.
With POST received the following error
_response": "{
\"error\": {
\"code\": \"parameter_missing\",
\"doc_url\": \"https://stripe.com/docs/error-codes/parameter-missing\",
\"message\": \"Missing required param: amount.\",
\"param\": \"amount\",
\"type\": \"invalid_request_error\"
}
}
With GET method received the following error
"_response":"resource exceeds maximum size"
End Point URL:-
let data = JSON.stringify({
customer: customerId,
currency: 'inr',
amount: 1000,
'automatic_payment_methods[enabled]': 'true',
});
let config = {
method: 'GET',
url: 'https://api.stripe.com/v1/payment_intents',
headers: {
Authorization:
'Bearer sk_test_DmXI7Jw1PnJAWYps3iCpvKkttIGX00pPfGLTjj',
'Content-Type': 'application/x-www-form-urlencoded',
},
data: data,
};
axios(config)
.then(function (response) {
console.info(JSON.stringify(response));
})
.catch(function (error) {
console.error('-----', error.response);
});
Following this document
https://stripe.com/docs/payments/accept-a-payment?platform=react-native&ui=payment-sheet#react-native-flowcontroller
https://stripe.com/docs/api/payment_intents/create
Added snack URL to reproduce the issue.
https://snack.expo.dev/#vishaldhanotiya/stripe-payment-intent
Error Log
To clarify a few things:
1/ You shared your (test mode) secret key in your code snippet, please delete that and roll your API keys (https://stripe.com/docs/keys#keeping-your-keys-safe).
2/ Your iOS/Android apps should not be making requests to Stripe's APIs directly with your secret API key, as that means you are bundling your secret key with your apps which means anyone running your app has access to your secret key.
Instead, you need to make requests from your iOS app to your server and your server should use Stripe's server-side libraries to make requests to Stripe's APIs. Your iOS/Android apps can only make requests with your publishable key.
3/ The PaymentIntent endpoint supports both POST and GET. You can create a PaymentIntent by POSTing to the /v1/payment_intents endpoint, you retrieve a single PaymentIntent with a GET to the /v1/payment_intents/:id endpoint and you list PaymentIntents with a GET to the /v1/payment_intents endpoint.
4/ The error in your POST request shows "Missing required param: amount." so you need to debug your code to make sure the amount parameter is getting through. You can use Stripe's Dashboard Logs page https://dashboard.stripe.com/test/logs to debug what parameters your code is sending to Stripe's API.
Finally, I found a solution. The issue occurred because I am send parameters without encoding.
I found a solution from this link
https://stackoverflow.com/a/58254052/9158543.
let config = {
method: 'post',
url: 'https://api.stripe.com/v1/payment_intents',
headers: {
Authorization:
'Bearer sk_test_51J3PfGLTjj',
'Content-Type': 'application/x-www-form-urlencoded'
}
};
let paymentDetail = {
customer: 'cus_MSiYLjtdaJPiCW',
currency: 'USD',
amount: 100,
'automatic_payment_methods[enabled]': true
};
let formBody: any = [];
for (let property in paymentDetail) {
let encodedKey = encodeURIComponent(property);
let encodedValue = encodeURIComponent(paymentDetail[property]);
formBody.push(encodedKey + '=' + encodedValue);
}
formBody = formBody.join('&');
const result = await axios
.post('https://api.stripe.com/v1/payment_intents', formBody, {
headers: config.headers
})
.then(function (response) {
console.info(JSON.stringify(response));
})
.catch(function (error) {
console.error('-----', error.response);
});

Vuejs axios get request always fetch new values [duplicate]

I am trying to query a quote API for a freeCodeCamp project I'm updating to React.js. I am now trying to use Fetch or Axios to query the API but it's caching the response in the browser. I know in $ajax there is a { cache: false } that would force the browser to do a new request.
Is there some way I will be able to do the same with Fetch or Axios?
The cache-control setting seems to be already set to max-age: 0 by Axios.
This is my code I have that is querying the API.
generateQuote = () => {
axios.get('https://quotesondesign.com/wp-json/posts?filter[orderby]=rand&filter[posts_per_page]=1')
.then(response => {
const { title, content, link } = response.data[0];
console.log(title, content, link)
this.setState(() => ({ title, content, link }));
})
.catch(err => {
console.log(`${err} whilst contacting the quote API.`)
})
}
Okay so I found a solution. I had to set a timestamp on the API url to get it to make a new call. There doesn't seem to be a way to force axios or fetch to disable cache.
This is how my code now looks
axios.get(`https://quotesondesign.com/wp-json/posts?filter[orderby]=rand&filter[posts_per_page]=1&timestamp=${new Date().getTime()}`)
.then(response => {
const { title, content, link } = response.data[0];
console.log(title, content, link)
this.setState(() => ({ title, content, link }));
})
.catch(err => {
console.log(`${err} whilst contacting the quote API.`)
})
I added these headers to all axios requests and it's working well.
axiosInstance.defaults.headers = {
'Cache-Control': 'no-cache',
'Pragma': 'no-cache',
'Expires': '0',
};
If you do not want to disable caching for all axios requests, you can disable caching for only one request by using the following parameters in the axios call:
axios.get(
'https://YOUR-URL.com',
{
// query URL without using browser cache
headers: {
'Cache-Control': 'no-cache',
'Pragma': 'no-cache',
'Expires': '0',
},
}
)
It seems, adding timestamp is the only always working way.
If you're using Vue, for example:
const api = axios.create({
baseURL: 'https://example.com/api',
params: {
t: new Date().getTime()
}
})
Vue.prototype.$api = api
So you can use it with:
this.$api.get('items')
And it will always add different timestamp to the url, depending on current request time.
I think you just need to make the url different each time you make the axios call. Timestamp is just one way to do so. Also consider disabling or filtering service workers caching method if you are developing a PWA.
Create an instance of axios and then add timestamp to every request.
const axiosInstance = axios.create({})
axiosInstance.interceptors.request.use(
function (config) {
// Do something before request is sent
config.params = { ...config.params, timestamp: Date.now() };
return config;
},
function (error) {
// Do something with request error
return Promise.reject(error);
}
);

Axios promise in VUE failed with Cannot read property 'toUpperCase' of undefined

In my SPA made in VUE I'm setting my Axios repository (or Api file) but I'm getting trouble using interceptors.
Basically, if the jwtoken is expired or missing the interceptor works and I see in the debug the 401 error and I see in network debug the attempt to the api server.
The issue is when I got a valid jwtoken. In this case I have no attempt in network window and the error:
TypeError: Cannot read property 'toUpperCase' of undefined
at dispatchXhrRequest (app.js:57825)
at new Promise (<anonymous>)
at xhrAdapter (app.js:57808)
at dispatchRequest (app.js:58416)
This should mean a promise error and maybe a config error, but I need fresh eyes to fix...
This is the request code having promise:
const headers = {
'X-CSRF-TOKEN': csrfToken,
'X-Requested-With': 'XMLHttpRequest',
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`,
};
client.interceptors.request.use(
config => {
if (!token) {
return config;
}
const newConfig = {
baseURL,
withCredentials: false,
headers: headers
};
return newConfig;
},
e => Promise.reject(e)
);
The stack trace suggests the problem is in dispatchXhrRequest. There's a call to toUpperCase here:
https://github.com/axios/axios/blob/2ee3b482456cd2a09ccbd3a4b0c20f3d0c5a5644/lib/adapters/xhr.js#L28
So it looks like you're missing config.method.
My guess would be that you need to copy the old config into your new config so you get all the other options, such as method:
const newConfig = {
...config,
baseURL,
withCredentials: false,
headers: headers
};

vue-resource not passing token in request headers

I'm new to Vuejs 2, currently using vue-resource to retrieve data from the server. However, I would need a token passed in the request header at the same time in order to retrieve the data from the server.
So the problem is, I am unable to retrieve data because the token is not passed into the request header, using vue-resource.
Here is the method that uses the vue-resource's interceptor (to pass in the token) to intercept the GET request:
test () {
this.$http.interceptors.push((request) => {
var accessToken = window.localStorage.getItem('access_token')
request.headers.set('x-access-token', accessToken)
return request
})
this.$http.get(staffUrl)
.then(response => {
console.log(response)
}, (response) => {
console.log(response)
})
}
Documentation for vue-resource, HTTP: https://github.com/pagekit/vue-resource/blob/develop/docs/http.md
When I try to GET the data, i end up with an error 403 (forbidden) and after checking the request headers in the dev tools, I also could not find the token in the request headers.
Please tell me where I went wrong because I'm really new to this so i appreciate any help! Thank you!
Setting interceptors inside the component using $http doesn't work, or at least it doesn't in my testing. If you examine/log this.$http.interceptors right after your push in the test method, you'll note that the interceptor was not added.
If you add the interceptor before you instantiate your Vue, however, the interceptor is added properly and the header will be added to the request.
Vue.http.interceptors.push((request, next) => {
var accessToken = "xyxyxyx"
request.headers.set('x-access-token', accessToken)
next()
})
new Vue({...})
Here is the test code I was using.
Also note, if you are using a version prior to 1.4, you should always call the next method that is passed to the interceptor. This does not appear to be necessary post version 1.4.
please go through this code
import vueResource from "vue-resource";
import { LocalStorage } from 'quasar'
export default ({
app,
router,
Vue
}) => {
Vue.use(vueResource);
const apiHost = "http://192.168.4.205:8091/";
Vue.http.options.root = apiHost;
Vue.http.headers.common["content-type"] = "application/json";
Vue.http.headers.common["Authorization"] = "Bearer " + LocalStorage.get.item("a_t");
Vue.http.interceptors.push(function(request, next) {
console.log("interceptors", request);
next(function(response) {
});
});
}