How do libraries to provide users a bindData function? - javascript

I need to copy the behaviour of, for example, the "create" function of Axios:
// fileOne.js
import axios from 'axios';
const instance = axios.create({
baseURL: 'https://some-domain.com/api'
});
Then to use that baseURL in another file, with another function like this:
// fileTwo.js
import axios from 'axios';
axios.get('/user/12345'); // https://some-domain.com/api/user/12345
Getting this as result:
https://some-domain.com/api/user/12345
How does Axios to bind the baseURL data in his library.
I'm looking that library but i don't understand how they do that.

Please see the official documentation Config Defaults section.
You can specify config defaults that will be applied to every request.
Global axios defaults
axios.defaults.baseURL = 'https://some-domain.com/api';
// use it later
axios.get('/user/12345')
Custom instance defaults
const instance = axios.create({
baseURL: 'https://some-domain.com/api'
});
// use it later
instance.get('/user/12345')
Source code explanation of axios v1.2.1
The Axios class has a defaults
property, axios will merge config when dispatch a request. The axios package will call createInstance to create an axios instance of the Axios class with built-in default config.
There is a buildFullPath function to build the full request URL use baseURL and requestedURL(Absolute or relative URL to combine, in your case, it's /user/12345)

Related

Problem with dynamic request header in axios template

In my react app, I created an api.js file which creates an api object with axios.create and exports it as default. So, I use that template to make the API requests. The problem is that, one of the headers in created axios api object must be dynamic.
For example, see the locale header below:
At first it may be something like this:
export default api = axios.create({
baseURL: process.env.REACT_APP_API_URL,
headers: {
post: {
"Content-Type": "application/json;charset=utf-8",
"Access-Control-Allow-Origin": "*",
locale: "en",
},
get: {
locale: "en",
},
},
});
But after some time it can be updated to some other locale, like "en" should be changed with "fr" for example. How can I update it, and make sure when it gets updated it changes in every place api is imported.
I can't use ContextApi etc, because I need to use that api in index.js file too, which, because of not being a react component, doesn't support use of hooks.
Sounds like a job for Axios interceptors...
import axios from "axios"
// some kind of storage for your locale
let locale = "en"
// some way of changing it
export const setLocale = (newLocale) => {
locale = newLocale
}
const api = axios.create({
baseURL: process.env.REACT_APP_API_URL,
})
// register a synchronous request interceptor
api.interceptors.request.use(config => ({
...config,
headers: {
...config.headers,
locale // merge the "locale" into the request config headers
}
}), null, { synchronous: true })
export default api
Also, Access-Control-Allow-Origin is a response header that comes from the server. It does not belong in your request and in general will more than likely cause CORS errors.
Also, the default content-type when posting JS objects in Axios is application/json so you typically don't need to set it.

How to mock an axios configuration module?

I have a module which configures axios:
// config/axiosConfig.js
import axios from 'axios';
const instance = axios.create({
baseURL: 'http://localhost:8080/api/v1'
});
export default instance;
And a module that uses this to make api calls:
// store/actions.ts
import axiosInstance from 'config/axiosConfig';
export const fetchUsers = () => (dispatch: ThunkDispatch<{}, {}, AnyAction>) => {
dispatch(loading(true));
return axiosInstance.get('/users')
.then(res => {
dispatch(loading(false));
dispatch(fetched(res.data));
})
.catch(err => dispatch(error(true)));
}
...
I want to mock the axios config file to test my api file. I've tried many many ways but nothing works. I thought it would be as simple as
// store/actions.test.ts
import axiosInstance from 'config/axiosConfig';
jest.mock('config/axiosConfig');
axiosConfig.get.mockResolvedValue({users: mockUserList});
...
But I guess that's not how it works.
Edit: The approach in my question works when I put axiosConfig.get.mockResolvedValue({users: mockUserList}); inside of the test, not right under the mock call.
Try this out (Put this at the top of the file or at the top inside beforeAll or beforeEach depending on what you prefer):
jest.mock('config/axiosConfig', () => ({
async get(urlPath) {
return {
users: mockUserList,
};
},
}));
This is a simple mock using a factory function. To use a mock everywhere, jest provides a better way to avoid repeating yourself. You create a __mocks__ directory and inside that, you can create your module and then override many of the builtins. Then, you can get away with just the following code.
// file.test.ts
jest.mock('fs')
// Rest of your testing code below
Take a look at the official docs to learn more about this.
If this doesn't work, then the module resolution setup in jest.config.js and tsconfig.js might be different.

How to modify the baseURL in axios depending on the current domain

What I'm trying to do is to create an Axios instance in my nuxt app and modify the baseURl to be the same as the domain but with some prefixes and import this instance from an external js file.
for example, I tried to interceptors the request and modify the domain but in the normal Axios package there is no referer to the current domain in '#nuxt/axios' module there is the referer of the current domain but only if I use the module:
axiosInstance.js:
import axios from 'axios';
// Note I don't want to use baseURL to be static.
const api = axios.craete();
api.interceptors.request.use( (config) => {
const prefixedDomain = prefixDomian(config.headers.common.refere)
config['baseURL'] = prefixedDomain
return config;
}, (error)=> {
return Promise.reject(error);
});
export default api
test.js:
import api from 'axiosService';
const settings = async () => {
const setting = await api.get('/settings');
return settings
}
export default settings
but this code doesn't work because the header is empty inside the config.
The only result that I want is to create an Axios instance with the baseURL prefixed and can import it and use it in an external file.

Axios custom instance not working properly with next JS

So firstly i create custom axios instance with baseurl and export it like this:
import axios from 'axios';
const instance = axios.create({
baseURL: process.env.BACKEND_URL,
});
instance.defaults.headers.common['Authorization'] = 'AUTH TOKEN';
instance.defaults.headers.post['Content-Type'] = 'application/json';
export default instance;
The problem is in my saga or in any component in general (ONLY client side) when importing this custom axios instance. I use next-redux-wrapper, and when i prefetch data (using getStaticProps) for my component everything works fine and the axios.defaults.baseURL property works just fine.
However the problem is on client-side, whenever i import the same axios instance in any component or in saga but i call it from lets say componentDidMount, the same axios.default.baseURL is undefined, so if i want to make get request i have to type in the full backend + queries URL. What could the problem be? EXAMPLE:
export function* fetchTPsSaga() {
try {
console.log(axios.defaults.baseURL);
const url = `/training-programs`;
const res = yield axios.get(url);
const tPs = res.data.data;
yield put(fetchTrainingProgramsSuccess(tPs));
} catch (err) {
yield put(fetchTrainingProgramsFail(err));
}
}
// The first time it renders (on server side), it's the valid baseURL property, however if i call the same saga from client-side (when component is rendered) it's UNDEFINED, so i have to type the full url
process.env only work on server-side. You can use publicRuntimeConfig to access environment variables both on client and server-side.
next.config.js
module.exports = {
publicRuntimeConfig: {
// Will be available on both server and client
backendUrl: process.env.BACKEND_URL,
},
}
axios instance file
import axios from 'axios';
import getConfig from 'next/config';
const { publicRuntimeConfig } = getConfig();
const instance = axios.create({
baseURL: publicRuntimeConfig.backendUrl,
});
By the way, if you are using Next.js versions 9.4 and up, the Environment Variables provide another way.
Loading Environment Variables Rules
In order to expose a variable to the browser you have to prefix the variable with
NEXT_PUBLIC_
. For example:
NEXT_PUBLIC_BACKEND_URL='http://localhost:3000'
Then you can access this env variable in Axios as its client-side rendering
import axios from 'axios';
const instance = axios.create({
baseURL: process.env.NEXT_PUBLIC_BACKEND_URL,
});
*Note: You have to use process.env.NEXT_PUBLIC_BACKEND_URL instead of process.env.BACKEND_URL

How to change the dynamic baseUrl Laravel + Vue.js?

How do I set the baseUrl so if I switch from server to server on the frontend (Vue.js), it changes dynamically to baseUrl?
I show my code axios-auth.js code:
import axios from 'axios'
const instance = axios.create({
baseURL: 'http://mvp.test/api/public/api/'
// baseURL: 'http://127.0.0.1:8000/api/' for testing localhost
});
and my .env file which have standard code for laravel.
Taken from the official mix documentation, you can use an environment variable by creating a key in your .env prefixed with MIX_:
MIX_BASE_URL=http://mvp.test/api/public/api/
And run php artisan config:clear to be sure the new config is set.
Then, in javascript you can access the variable inside the process.env object:
process.env.MIX_BASE_URL
So you can simply use it like this:
const instance = axios.create({
baseURL: process.env.MIX_BASE_URL
});

Categories