capacitor community/http handle errors - ionic-framework

I often use Axios to perform requests in my applications, however due to incompatibility with iphone, I had to use the capacitor-community/http library, however the try catch blocks are always returning success, even if there was an error in the request. How can I handle errors using this library?
try {
await Requester.auth.public.login(formData);
this.$store.dispatch('login', user);
this.$root.$emit('showToast', {
text: 'Seja bem vindo!',
color: 'success',
});
this.$router.push({ name: 'Cotacao' });
} catch (err) {
this.$root.$emit('showToast', {
text: err.response?.data ?? err.toString(),
color: 'error',
});
} finally {
this.loading.submitForm = false;
}
},
My request
const login = async (formData: AuthLoginFormData): Promise<User> => {
const res: HttpResponse = await Http.post({
url: `${BASE_URL}public/auth/login`,
headers: {
'Content-Type': 'application/json',
},
data: formData,
webFetchExtra: {
credentials: 'include',
},
});
return res.data;
};

Install Latest https://github.com/capacitor-community/http plugin
use function
public async login(formData: AuthLoginFormData){
let options = {
url: `${BASE_URL}public/auth/login`,
headers: {
'Content-Type': 'application/json',
},
data: formData,
webFetchExtra: {
credentials: 'include',
}
};
let response: HttpResponse = await Http.request(options);
if (response.status === 200) {
return Promise.resolve(res);
}
return Promise.reject(response.data);
}

Related

How do I use Axios GET Params using a search input

I'm trying to send GET request and I also want to fetch the data using the search input. So I have used Params but it is not working ,
here's my code :
// setFetching(true)
let url = `${TEST_API_URL}/teammember/getAll`
try {
const posts: any = await axios.get(`${url}`, {
withCredentials: true,
headers: {
Authorization: `${localStorage.getItem('access_token')}`,
},
params: {
search
},
})
console.log(posts.data.Data)
setPosts(posts.data.Data)
} catch (error: any) {
toast.error('Something went wrong')
}
// setFetching(false)
}, [search])
useEffect(() => {
async function fetchData() {
await fetchFunction()
}
void fetchData()
}, [fetchFunction])```
I recommend you to do like this.
// setFetching(true)
let url = `${TEST_API_URL}/teammember/getAll`
try {
const posts: any = await axios.get(`${url}?search=${search}`, {
withCredentials: true,
headers: {
Authorization: `${localStorage.getItem('access_token')}`,
}
})
console.log(posts.data.Data)
setPosts(posts.data.Data)
} catch (error: any) {
toast.error('Something went wrong')
}
// setFetching(false)
}, [search])
useEffect(() => {
async function fetchData() {
await fetchFunction()
}
void fetchData()
}, [fetchFunction])```

NextJS axios interceptors set/get cookie

Using NextJS 12 and axios to try to get and set a cookie in the interceptor on the server side with no luck. Does anyone know how to get/set cookie in this instance?
const axiosApiInstance = axios.create({ withCredentials: true });
axiosApiInstance.interceptors.request.use(
async config => {
config.headers = {
'Authorization': `Bearer ${config.headers.cookie}`,
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded'
}
config.withCredentials = true;
return config;
},
error => {
Promise.reject(error);
}
);
axiosApiInstance.interceptors.response.use((response) => {
response.headers.cookie = cookie.serialize(
"token",
"hello world"
)
return response;
}, async function(error) {
return Promise.reject(error);
}
);
Is there someway I can pass the cookie as an argument to the interceptor?
const response = await axiosApiInstance.post(cookie??, url, data, { headers: cookie?? }}

Why does delete method not updated the list?

Working Todo application using VueJS, Vuex and MongoDB, after delete a task my list does not updated without refresh page. I already add a dispatch GET_TASK in promise awaiting the list update, but it is not working, and seems which this promise even not execute.
<template>
<div class="flex-col mx-auto mt-10 min-w-max font-sans text-xl" style="width:512px">
<ul class="space-y-2">
<li class="flex justify-between px-4 min-h-full" v-for="task in tasks" :key="task.id">
{{task.task}}
<button #click="deletetodo(task._id)" class="text-xs border-2 px-4 focus:outline-none hover:bg-blue-200 hover:text-white rounded-full">Delete</button>
</li>
</ul>
</div>
</template>
<script>
export default {
name:"ListToDo",
computed:{
tasks: function(){
return this.$store.state.task
}
},
methods:{
async getlisttodo(){
await this.$store.dispatch("GET_TASK")
},
async deletetodo(id){
await this.$store.dispatch("DELETE_TASK",{'id':id})
.then(response => {
this.$store.dispatch("GET_TASK")
console.log(response);
})
.catch(error => console.log(`DeleteTodo ${error}`))
}
},
mounted(){
this.getlisttodo()
}
}
</script>
Vuex:
actions: {
async GET_TASK({ commit }) {
const rawResponse = await fetch('http://localhost:3000/tasks')
const content = await rawResponse.json();
commit("SET_TASK", content)
},
async SAVE_TASK({ commit }, object) {
const rawResponse = await fetch('http://localhost:3000/save', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({ 'task': object })
});
const content = await rawResponse.json();
commit("SET_MESSAGE", content)
},
async DELETE_TASK({ commit }, obj) {
const id = obj['id']
const raw = await fetch(`http://localhost:3000/delete/${id}`, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({ 'id': id })
});
const content = await raw.json();
commit("SET_MESSAGE", content)
}
}
Just skimming through it seems that you are awaiting an async method and also doing .then.
If you are awaiting a method, then the task will wait until it fullfills the promise before going to the next line.
(more info on async/await here)
Also I'm not sure if response is being returned when you are dispatching "DELETE_TASK". I see a "SET_MESSAGE" being called within that method. You can always check my console.logging.
if that's the case try changing delete todo method as follows
async deletetodo(id){
try{
let response = await this.$store.dispatch("DELETE_TASK",{'id':id});
this.$store.dispatch("GET_TASK");
console.log(response);
}
catch(error){
console.log(`DeleteTodo ${error}`)
}
}
Happy Coding!
I got to fix that by adding DELETE METHOD
vuex:
async DELETE_TASK({ commit }, obj) {
try {
const id = obj['id']
const raw = await fetch(`http://localhost:3000/delete/${id}`, {
method: 'DELETE',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({ 'id': id })
});
const content = await raw.json();
commit("SET_MESSAGE", content)
} catch (error) {
console.log(`DELETE_TASK ${error}`)
}
}
server.js
app.delete('/delete/:id', async(req, res) => {
try {
const id = req.body.id;
TodoTask.findByIdAndDelete(id, err => {
if (err) return res.send(500, err);
res.send({ 'status': 200, "mensagem": 'Tarefa deletada' })
})
} catch (error) {
console.log(`Error Delete ${error}`)
}
})
ListTodo.vue
methods:{
async deletetodo(id){
try{
await this.$store.dispatch("DELETE_TASK",{'id':id})
.then(response => {
this.$store.dispatch("GET_TASK");
console.log(response);
})
.catch(error => console.log(error))
}catch(error){
console.log(`DeleteTodo ${error}`);
}
}
}

How to add additional headers and token for each tile request

We are using mapbox gl js with custom tile providers and tiles are protected by token. In our case each tile will have its own token and fetched via AJAX request on demand. In order to achieve this i tried to use tranformRequest option like below but none of them works
Method 1 Returning promise
var map = new mapboxgl.Map({
container: 'map',
style: 'https://www.example.com/styles/streets/style.json',
center: [53.33, 24.5],
zoom: 8,
transformRequest: function(url, resourceType) {
if(resourceType !== 'Tile') {
return {
url: url,
};
}
return axios.get('../api/get-token.php', {
params: {
AccessURL: url
},
headers: {
'X-Requested-With': 'XmlHttpRequest'
}
}).then(function (response) {
return {
url: url,
headers: {
'X-Requested-With': 'XmlHttpRequest'
'token': response.data.token
}
}
});
}
});
Method 2 async/await
var map = new mapboxgl.Map({
container: 'map',
style: 'https://www.example.com/styles/streets/style.json',
center: [53.33, 24.5],
zoom: 8,
transformRequest: async function(url, resourceType) {
if(resourceType !== 'Tile') {
return {
url: url,
};
}
try {
const response = await axios.get('../api/get-token.php', {
params: {
AccessURL: url
},
headers: {
'X-Requested-With': 'XmlHttpRequest'
}
});
return {
url: url,
headers: {
'X-Requested-With': 'XmlHttpRequest'
'token': response.data.token
}
};
} catch (error) {
return {
url: url,
};
}
}
});
How can i achieve this cases? is there any options exists in mapbox gl js library or any workaround ?
I don't believe transformRequest can accept an async parameter such as a promise. It expects to call a function and immediately receive an object containing url and headers:
{
...
transformRequest: function transformRequest(url, resourceType) {
if (resourceType === 'Tile' && url.match('...')) {
return {
url: url,
headers: { 'Authorization': 'Basic ' + btoa('MyPassword') }
};
}
}
If your use case truly requires a unique authentication token for every single tile (which seems...unusual!) then I'm not aware of a method which will work.

Passing headers with axios POST request

I have written an Axios POST request as recommended from the npm package documentation like:
var data = {
'key1': 'val1',
'key2': 'val2'
}
axios.post(Helper.getUserAPI(), data)
.then((response) => {
dispatch({type: FOUND_USER, data: response.data[0]})
})
.catch((error) => {
dispatch({type: ERROR_FINDING_USER})
})
And it works, but now I have modified my backend API to accept headers.
Content-Type: 'application/json'
Authorization: 'JWT fefege...'
Now, this request works fine on Postman, but when writing an axios call, I follow this link and can't quite get it to work.
I am constantly getting 400 BAD Request error.
Here is my modified request:
axios.post(Helper.getUserAPI(), {
headers: {
'Content-Type': 'application/json',
'Authorization': 'JWT fefege...'
},
data
})
.then((response) => {
dispatch({type: FOUND_USER, data: response.data[0]})
})
.catch((error) => {
dispatch({type: ERROR_FINDING_USER})
})
When using Axios, in order to pass custom headers, supply an object containing the headers as the last argument
Modify your Axios request like:
const headers = {
'Content-Type': 'application/json',
'Authorization': 'JWT fefege...'
}
axios.post(Helper.getUserAPI(), data, {
headers: headers
})
.then((response) => {
dispatch({
type: FOUND_USER,
data: response.data[0]
})
})
.catch((error) => {
dispatch({
type: ERROR_FINDING_USER
})
})
Here is a full example of an axios.post request with custom headers
var postData = {
email: "test#test.com",
password: "password"
};
let axiosConfig = {
headers: {
'Content-Type': 'application/json;charset=UTF-8',
"Access-Control-Allow-Origin": "*",
}
};
axios.post('http://<host>:<port>/<path>', postData, axiosConfig)
.then((res) => {
console.log("RESPONSE RECEIVED: ", res);
})
.catch((err) => {
console.log("AXIOS ERROR: ", err);
})
To set headers in an Axios POST request, pass the third object to the axios.post() call.
const token = '..your token..'
axios.post(url, {
//...data
}, {
headers: {
'Authorization': `Basic ${token}`
}
})
To set headers in an Axios GET request, pass a second object to the axios.get() call.
const token = '..your token..'
axios.get(url, {
headers: {
'Authorization': `Basic ${token}`
}
})
const data = {
email: "me#me.com",
username: "me"
};
const options = {
headers: {
'Content-Type': 'application/json',
}
};
axios.post('http://path', data, options)
.then((res) => {
console.log("RESPONSE ==== : ", res);
})
.catch((err) => {
console.log("ERROR: ====", err);
})
All status codes above 400 will be caught in the Axios catch block.
Also, headers are optional for the post method in Axios
You can also use interceptors to pass the headers
It can save you a lot of code
axios.interceptors.request.use(config => {
if (config.method === 'POST' || config.method === 'PATCH' || config.method === 'PUT')
config.headers['Content-Type'] = 'application/json;charset=utf-8';
const accessToken = AuthService.getAccessToken();
if (accessToken) config.headers.Authorization = 'Bearer ' + accessToken;
return config;
});
Shubham's answer didn't work for me.
When you are using the Axios library and to pass custom headers, you need to construct headers as an object with the key name 'headers'. The 'headers' key should contain an object, here it is Content-Type and Authorization.
The below example is working fine.
var headers = {
'Content-Type': 'application/json',
'Authorization': 'JWT fefege...'
}
axios.post(Helper.getUserAPI(), data, {"headers" : headers})
.then((response) => {
dispatch({type: FOUND_USER, data: response.data[0]})
})
.catch((error) => {
dispatch({type: ERROR_FINDING_USER})
})
We can pass headers as arguments,
onClickHandler = () => {
const data = new FormData();
for (var x = 0; x < this.state.selectedFile.length; x++) {
data.append("file", this.state.selectedFile[x]);
}
const options = {
headers: {
"Content-Type": "application/json",
},
};
axios
.post("http://localhost:8000/upload", data, options, {
onUploadProgress: (ProgressEvent) => {
this.setState({
loaded: (ProgressEvent.loaded / ProgressEvent.total) * 100,
});
},
})
.then((res) => {
// then print response status
console.log("upload success");
})
.catch((err) => {
// then print response status
console.log("upload fail with error: ", err);
});
};
axios.post can accept 3 arguments that the last argument can accept a config object that you can set header.
Sample code with your question:
var data = {
'key1': 'val1',
'key2': 'val2'
}
axios.post(Helper.getUserAPI(), data, {
headers: {Authorization: token && `Bearer ${ token }`}
})
.then((response) => {
dispatch({type: FOUND_USER, data: response.data[0]})
})
.catch((error) => {
dispatch({type: ERROR_FINDING_USER})
})
If you are using some property from vuejs prototype that can't be read on creation you can also define headers and write i.e.
storePropertyMaxSpeed(){
axios
.post(
"api/property",
{
property_name: "max_speed",
property_amount: this.newPropertyMaxSpeed,
},
{
headers: {
"Content-Type": "application/json",
Authorization: "Bearer " + this.$gate.token(),
},
}
)
.then(() => {
//this below peace of code isn't important
Event.$emit("dbPropertyChanged");
$("#addPropertyMaxSpeedModal").modal("hide");
Swal.fire({
position: "center",
type: "success",
title: "Nova brzina unešena u bazu",
showConfirmButton: false,
timer: 1500,
});
})
.catch(() => {
Swal.fire("Neuspješno!", "Nešto je pošlo do đavola", "warning");
});
};
Interceptors
I had the same issue and the reason was that I hadn't returned the response in the interceptor. Javascript thought, rightfully so, that I wanted to return undefined for the promise:
// Add a request interceptor
axios.interceptors.request.use(function (config) {
// Do something before request is sent
return config;
}, function (error) {
// Do something with request error
return Promise.reject(error);
});