How do I make this axios call inside my own API route? - express

This is my first time trying to make an API call to a third party while inside my own API route. The following code does not work because I get the error "Cannot use import statement outside a module." This code is called by a thunk at the front end.
If I can't import axios, what's an alternative?
EDIT: I got rid of the error by doing 'const axios = require('axios') but now the results I'm getting is undefined.
EDIT2: Resolved. Through use of the following:
router.get("/:zip", async (req, res, next) => {
try {
let data = [];
await axios
.get(`https://api.yelp.com/v3/businesses/search`, {
headers: {
Authorization: `Bearer ${process.env.SECRET_KEY_YELP}`,
},
params: {
location: req.params.zip,
// categories: "coffee",
},
})
.then((response) => {
data = response.data;
});
res.send(data);
} catch (err) {
next(err);
}
});
ORIGINAL CODE WITH ISSUE:
const router = require("express").Router();
module.exports = router;
import axios from "axios";
router.get("/:zip", async (req, res, next) => {
try {
//const restaurants = await Test.findAll({})
const result = await axios.get(
`https://api.yelp.com/v3/businesses/search?location=${req.params.zip}`,
{
headers: {
Authorization: `Bearer ${process.env.SECRET_KEY_YELP}`,
},
params: {
categories: "coffee",
},
}
).data;
res.send(result);
} catch (err) {
next(err);
}
});

Posted above. It needed a .then snippet.
let data = [];
await axios
.get(`https://api.yelp.com/v3/businesses/search`, {
headers: {
Authorization: `Bearer ${process.env.SECRET_KEY_YELP}`,
},
params: {
location: req.params.zip,
// categories: "coffee",
},
})
.then((response) => {
data = response.data;
});
res.send(data);

Related

Axios interceptors not adding headers on some requests in React Native, iOS only

I have an Axios instance:
const axiosInstance = axios.create({
baseURL: API_URL,
timeout: 5000,
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
},
});
axiosInstance.interceptors.request.use(async (config: any) => {
const accessToken = await getSecureValue('accessToken');
config.headers.Authorization = `Bearer ${accessToken}`;
return config;
});
And some API functions:
export const getProfile = async () => {
const response = await axiosInstance.get('/user/profile');
return response.data;
};
export const postContact = async (message: string) => {
await axiosInstance.post('/contact', { message });
};
A user can log in and it calls getProfile(), that all works.
But when I try the postContact:
const handleSendPress = async () => {
try {
await postContact(textInput);
} catch (error) {
console.log(error);
}
};
It comes back with an error from the server that the Authorization header is missing.
Adding a console.log() in the interceptor I can see that it is running before the request.
I'm running Android and iOS in emulators, and this only happens on iOS.
I'm very lost what this could be, since getProfile() works but postContact() doesn't and they both use the same Axios instance.

How to send axios reques in react native?

I'm new to React Native and I'm trying to send axios request to my backend but I'm stuck in it.
export const login = (email, password) => async dispatch => {
const config = {
headers: {
'Content-Type': 'application/json'
}
};
const body = JSON.stringify({ email, password });
const res = await axios.post(`http://localhost:8000/auth/jwt/create/`, body, config);
console.log('kk');
dispatch({
type: LOGIN_SUCCESS,
payload: res.data
});
dispatch(load_user());
};
when it tries to post request through axios it gives following error.
although I haved tried this in React JS and it's working perfectly.
please help me to solve this in react native
Per the React Native Networking Docs, React Native supports the fetch web API for sending requests. I advise you use fetch instead of axios as it has all of the same features without any added bloat and overhead. Here is a port of your code to use fetch:
export const login = (email, password) => async (dispatch) => {
const res = await fetch(`http://localhost:8000/auth/jwt/create/`, {
method: "POST", // this signnifies POST request type
body: JSON.stringify({ email, password }), // still including the body
headers: {
// apply the headers
"Content-Type": "application/json"
}
});
const data = await res.json(); // parses the body as a json object
console.log("kk");
dispatch({
type: LOGIN_SUCCESS,
payload: data
});
dispatch(load_user());
};
Try to use this way:
// define axios request
import axios from 'axios';
const request = axios.create({
baseURL: 'https://url.com/api/v1',
timeout: 20000,
});
request.interceptors.request.use(
config => {
// config.headers.Authorization = `Bearer ${token}`;
config.headers.Accept = 'Application/json';
return config;
},
error => {
//return Promise.reject(error);
console.log("interceptors.request: ", error);
return false;
},
);
request.interceptors.response.use(
response => {
if (response && response.data) {
return response.data;
}
return response;
},
error => {
console.log('Response error: ', error);
//throw error;
return false;
},
);
export default request;
Usage:
import request from '../';
export const getAPI = () => {
return request({
url: '/getData',
method: 'GET',
// ...
});
};
getAPI().then(response => {
//...
});

UseEffect to run a function and that function set hook from another file

So what I want to do is throw my APIs in one file. This way it makes my app way more reusable.
Problem is that I don't know how to do what I'm doing.
My parent file holds all the Hooks I need for data.
I am trying to get the Parent file to call the API, run the call to get the data, then that data then calls back and sets the hook in the parent.
Parent File
import { handleDepartments } from './API/API';
export default function App() {
const [departments, setDepartments] = useState([]);
useEffect(() => {
handleDepartments;
}, []);
The API file..
export const handleDepartments = async () => {
console.log('getting Departments');
const data = await axios
.get(`URI`, {
headers: {
Authorization: 'API_KEY',
Accept: 'application/json',
},
})
.then((response) => {
setDepartments(response.data.departments);
})
.catch((err) => {
console.log(err);
});
};
You're on the right track but its not a great idea to pass down a setState function into the api to update the parent component. Instead, its better practice to make the api call only return data, then the parent can decide how to deal with it.
Api:
export const handleDepartmentsApi = async () => {
await axios
.get(`URI`, {
headers: {
Authorization: 'API_KEY',
Accept: 'application/json',
},
})
.then((response) => {
return data;
})
.catch((err) => {
return err;
});
};
Parent:
export default function App() {
const [departments, setDepartments] = useState([]);
const getDepartments = async () => {
try {
const response = await handleDepartmentsApi();
setDepartments(response.data.departments)
} catch (err) {
//handle error or do whatever
}
}
useEffect(() => {
getDepartments();
}, []);
return (<></>)
}

Mock .get() Function using Jest on VueJS

I am trying to mock a GET request to get some Posts using the ID. This is the code I am trying to mock:
getPost() {
this.refreshToken();
http
.get(`/posts/${this.$cookie.get('postid')}`, {
headers: {
"Authorization": `Bearer ${this.$cookie.get('token')}`,
"Content-type": "application/json",
},
})
.then((response) => {
this.post = response.data;
})
.catch((error) => {
console.log(error.response);
});
}
This is my attempt at a test:
import {getPost} from '#/views/Post.vue'
import axios from 'axios';
jest.mock('axios');
describe('get Post by ID', () => {
afterEach(() => {
jest.resetAllMocks();
});
it('should return empty when axios.get failed', async () => {
const getError = new Error('error');
axios.get = jest.fn().mockRejectedValue(getError);
const actualValue = await getPost();
expect(actualValue).toEqual(new Map());
expect(axios.get).toBeCalledWith('/posts/postid');
});
it('should return users', async () => {
const mockedUsers = [{ postID: 1 }];
axios.get = jest.fn().mockResolvedValue(mockedUsers);
const actualValue = await getPost(['1']);
expect(actualValue).toEqual(mockedUsers);
expect(axios.get).toBeCalledWith('/posts/postid');
});
})
The error I am getting is:
TypeError: (0 , _Post.getPost) is not a function
I am not sure what to do, and any help would be super appreciated. Thanks!
Assuming you have getPost() defined in the Post component's methods, you can't use named imports to access getPost. Instead, you'll have to mount the component, and use the wrapper's vm:
// Post.spec.js
import { shallowMount } from '#vue/test-utils'
import Post from '#/views/Post.vue'
it('...', () => {
const wrapper = shallowMount(Post)
await wrapper.vm.getPost()
expect(wrapper.vm.post).toEqual(...)
})
Also make sure to return the axios call in getPost() so that it could be awaited:
// Post.vue
export default {
methods: {
getPost() {
this.refreshToken();
👇
return http.get(/*...*/)
.then(/*...*/)
.catch(/*...*/);
}
}
}

Check if token still valid before request

I am using an index.js file to make api calls in a vue app. Is there a way to add a catch or a before each call to see if my token is still good and have the user redirected to login if it isnt?
import axios from 'axios'
const client = axios.create({
baseURL : 'http://myapi.com/api/',
json: true
})
export default {
async execute(method, resource, data) {
const token = localStorage.getItem('token')
return client({
method,
url: resource,
data,
crossdomain: true ,
headers: { "Authorization": `Bearer ${token}` }
}).then(req => {
return req.data
})
},
getResponses() {
return this.execute('get', 'GetResponses')
},
getAll(){
return this.execute('get', 'GetAll')
},
You can use an interceptor, where you can pass a function to be called before each request:
const client = axios.create({ baseURL: 'http://myapi.com/api/', json: true });
client.interceptors.request.use((config) => {
const token = localStorage.getItem('token');
if (isTokenGood(token)) {
return config;
} else {
logout();
}
});
If anyone is interested i ended up going with an interceptor as per #thanksd
My code index.js file in my api folder now looks like this
import axios from 'axios'
import router from '../router'
const client = axios.create({
baseURL : 'http://myapi.com/api/',
json: true
})
client.interceptors.response.use(function (response) {
return response
}, function (error) {
if (error.response.status === 401) {
router.push('/Login')
console.info('auth token expired')
localStorage.clear()
sessionStorage.clear()
} else if (error.response.status === 403) {
router.push('/Login')
} else {
return Promise.reject(error)
}
})
export default {
async execute(method, resource, data) {
const token = localStorage.getItem('token')
return client({
method,
url: resource,
data,
crossdomain: true ,
headers: { "Authorization": `Bearer ${token}` }
}).then(req => {
return req.data
})
},
getResponses() {
return this.execute('get', 'GetResponses')
},
getAll(){
return this.execute('get', 'GetAll')
},