How can I use axios.defaults.baseURL conditionally? [duplicate] - javascript

I am having a config file . where i am setting the baseURL for the entire app and also saving the bearer token for the entire API requests. Here i am in situation to add another api . I dont know how to add another baseURL & use this on my API requests.Here i am sharing the code of what i have done.
BASE URL FILE:
import axios from 'axios';
axios.defaults.baseURL = http://localhost:3000/summary;
const setAuthToken = (token) => {
if (token) {
axios.defaults.headers.common.Authorization = `Bearer ${token}`;
} else {
delete axios.defaults.headers.common.Authorization;
}
};
export default setAuthToken;
API ACTION FILE:
export const login = ({ email, password }) => async (dispatch) => {
const userData = {
username: email,
password,
};
try {
const res = await axios.post('/license-api/auth/login', userData, config);
dispatch({
type: LOGIN_SUCCESS,
payload: res.data.token,
});
} catch (error) {
dispatch({
type: LOGIN_FAIL,
});
}
};
i need to add another url like this in BASE URL FILE
axios.defaults.baseURL = http://localhost:6000/profile
how to add this one and use this in API action file.
Please help me with this.
Thanks in advance

As said you could create two instances of axios and use them as needed:
In you BASE URL file:
import axios from 'axios';
const setAuthToken = (token) => {
if (token) {
axios.defaults.headers.common.Authorization = `Bearer ${token}`;
} else {
delete axios.defaults.headers.common.Authorization;
}
};
const mainAxios = axios.create({
baseURL: 'http://localhost:3000/summary'
});
const profileAxios = axios.create({
baseURL: 'http://localhost:6000/profile'
});
export default setAuthToken;
export { mainAxios, profileAxios };
Then in your API ACTION file:
import { profileAxios } from 'path/to/baseurl';
export const login = ({ email, password }) => async (dispatch) => {
const userData = {
username: email,
password,
};
try {
const res = await profileAxios.post('/license-api/auth/login', userData, config);
dispatch({
type: LOGIN_SUCCESS,
payload: res.data.token,
});
} catch (error) {
dispatch({
type: LOGIN_FAIL,
});
}
};

The above code works well. I don't see where setAuthToken is called so if you don't want to call setAuthToken manually then you might want to do this.
import axios from "axios";
import { config } from "./config";
const pythonAPI = axios.create({
baseURL: config.pythonServerUrl,
});
const nodeApi = axios.create({
baseURL: config.nodeServerUrl,
});
const setToken = () => {
const token = localStorage.getItem("auth_token");
if (token) {
pythonAPI.defaults.headers.common.Authorization = `Basic ${token}`;
} else {
delete pythonAPI.defaults.headers.common.Authorization;
}
};
const pythonApi = {};
pythonApi.get = async (url) => {
setToken();
return pythonAPI.get(url).catch((e) => e.response);
};
pythonApi.post = async (url, data) => {
setToken();
return pythonAPI.post(url, data).catch((e) => e.response);
};
export { pythonApi, nodeApi };

Related

How to get the raw string of cookie using js-cookie

I am trying to use js-cookie to store access_token as cookies in the cookie strorage. But whenever I set the cookie, it gets displayed like this: %22eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjU5NDIzOTA3LCJpYXQiOjE2NTg1NTk5MDcsImp0aSI6IjAyMmRlMTg2MTk0NzRhYzY5ZThjOTVmOGNhZDE3OTM4IiwidXNlcl9pZCI6Mn0.xkOTI4uO93_YIvlGrcnnKLFjbLZiM_RdNo9J9A8Clk4%22
But I dont want it that way. I weant to get the token without "%22" at the beginning and end.
This is my code. Thank you.
import {createContext, useState, useEffect} from 'react'
import Cookie from "js-cookie";
import jwt_decode from "jwt-decode"
import {useHistory} from 'react-router-dom'
const SetCookie = (cookiename, cookie) => {
Cookie.set(cookiename, cookie)
}
const GetCookie = (cookiename) => {
return Cookie.get(cookiename)
}
const AuthContext = createContext()
export default AuthContext
export const AuthProvider = ({children}) => {
let [authTokens, setAuthTokens] = useState(localStorage.getItem('authTokens') ? JSON.parse(localStorage.getItem('authTokens')):null)
let [user, setUser] = useState(localStorage.getItem('authTokens') ? JSON.parse(localStorage.getItem('authTokens')):null)
const histroy = useHistory()
histroy.push('/')
let loginUser = async (e)=> {
e.preventDefault()
let response = await fetch('http://127.0.0.1:8000/users/login/', {
method: "POST",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
body:JSON.stringify({'email':e.target.email.value, 'password':e.target.password.value})
})
let data = await response.json()
console.log('response:', response)
if (response.status === 200) {
setAuthTokens(data)
setUser(data)
SetCookie('cookie', JSON.stringify(data.access_token))
localStorage.setItem('authTokens', JSON.stringify(data))
} else{
alert('there was problem signing in')
}
}
let registerUser = async (e)=> {
e.preventDefault()
let response = await fetch('http://127.0.0.1:8000/users/register/', {
method: 'POST',
headers:{
'Content-Type':'application/json'
},
body:JSON.stringify({'username':e.target.username.value, 'email':e.target.email.value, 'password1':e.target.password1.value, 'password2':e.target.password2.value})
})
let data = await response.json()
console.log('response:', response)
if (response.status === 201) {
alert('An email verification message has been sent to your email address')
} else{
alert('Something went wrong! Check your credentials and try again')
}
}
let passwordReset = async (e)=> {
e.preventDefault()
let response = await fetch('http://127.0.0.1:8000/password-reset/', {
method: 'POST',
headers:{
'Content-Type':'application/json'
},
body:JSON.stringify({'email':e.target.email.value})
})
let data = await response.json()
console.log('response:', response)
}
let passwordresetConfirm = async (e)=> {
e.preventDefault()
let response = await fetch('http://127.0.0.1:8000/password-reset-confirm/', {
method: 'POST',
headers:{
'Content-Type':'application/json'
},
body:JSON.stringify({'new_password1':e.target.new_password1.value, 'new_password2':e.target.new_password2.value,})
})
let data = await response.json()
console.log('response:', response)
}
let logoutUser = () => {
setAuthTokens(null)
setUser(null)
localStorage.removeItem('authTokens')
histroy.push('/login')
}
let contextData = {
user:user,
loginUser : loginUser,
logoutUser : logoutUser,
registerUser : registerUser,
passwordReset : passwordReset,
passwordresetConfirm : passwordresetConfirm,
}
return(
<AuthContext.Provider value={contextData}>
{children}
</AuthContext.Provider>
)
}

next.js & next-auth When I send http request in getServerSideProps, getSession returns null in secured API Route

I am trying to secure the API Route and this API route is called in the Client and Server-side on different pages.
On the test page, it returns 401 error.
On the test2 page, it returns the content well.
I guess it doesn't pass session when I send the http request in the getServerSideProps.
My question is, how do I secure the API routes used on the client and server-side?
/pages/test
import React from 'react';
import axios from 'axios';
import { getSession } from 'next-auth/react';
const Test = (props) => {
return <div>test</div>;
};
export const getServerSideProps = async (context) => {
// it returns session data
const session = await getSession(context);
// it returns error
const res = await axios.get('/api/secret');
return {
props: {
session,
secret: res.data,
},
};
};
export default Test;
/pages/test2
import React, { useEffect } from 'react';
import axios from 'axios';
import { useSession, getSession } from 'next-auth/react';
const Test = (props) => {
const { data: session } = useSession();
useEffect(() => {
const fetchData = async () => {
const res = await axios.get('/api/secret');
console.log(res.data);
};
fetchData();
}, [session]);
return <div>test</div>;
};
export default Test;
/pages/api/secret
import { getSession } from 'next-auth/react';
const handler = (req, res) => {
const { method } = req;
switch (method) {
case 'GET':
return getSomething(req, res);
default:
return res.status(405).json('Method not allowed');
}
};
const getSomething = async (req, res) => {
const session = await getSession({ req });
console.log(session);
if (session) {
res.send({
content: 'Welcome to the secret page',
});
} else {
res.status(401).send({
err: 'You need to be signed in.',
});
}
};
export default handler;
I found a solution.
export const getServerSideProps = async (ctx) => {
const session = await getSession(ctx);
const headers = ctx.req.headers;
if (session) {
const data = (
await axios.get(`${process.env.NEXTAUTH_URL}/api/secret`, {
headers: { Cookie: headers.cookie },
})
return {
props: {
data,
},
};
} else {
return {
redirect: {
destination: '/login',
permanent: false,
},
};
}
};
/pages/api/secret
import { getSession } from 'next-auth/react';
const handler = async (req, res) => {
const { method } = req;
switch (method) {
case 'GET':
return await getSomething(req, res);
default:
return res.status(405).json('Method not allowed');
}
};
const getSomething = async (req, res) => {
const session = await getSession({ req });
// console.log(session);
if (session) {
res.send({
content: 'Welcome to the secret page',
});
} else {
res.status(401).send({
err: 'You need to be signed in.',
});
}
};
export default handler;
There is a specific method to handle request from serverSideProps, better than using useSession (which is meant for client requests)
https://next-auth.js.org/tutorials/securing-pages-and-api-routes#server-side
Best use unstable_getServerSession as mentioned in the documentation example
await unstable_getServerSession(req, res, authOptions)
with the authOptions coming as an export from your [...nextauth].js

Nodejs MongoDB - add new entry Post()

so trying to post new entry into MongoDB. but getting this error in Redux Product validation failed: name: Path 'name' is required., description: Path 'description' is required.
nodejs version: 14.9.0
and Atlas mongodb.
frontEnd addProduct.js page:
import { createProduct } from '../redux/actions/productActions'
const [name, setName] = useState('')
const [description, setDescription] = useState('')
const createProductHandler = (e) => {
e.preventDefault()
dispatch(createProduct({
name,
description
}))
}
const nameHandler = (e) => {
setName(e.target.value)
}
const descriptionHandler = (e) => {
setDescription(e.target.value)
}
return (
<input type='text' onChange={nameHandler} />
<input type='text' onChange={descriptionHandler} />
<input type="submit" value='submit' onClick={createProductHandler} />
)
productController:
const createdProduct = asyncHandler(async (req, res) => {
const mongoProduct = async (data) => {
return new Product({
name: data.name,
description: data.description
})
}
const product = await mongoProduct(req.body)
const createdProduct = await product.save()
res.status(201).json(createdProduct)
})
productActions:
export const createProduct = () => async (dispatch, getState) => {
try {
dispatch({
type: 'PRODUCT_CREATE_REQUEST',
})
const {
userLogin: {userInfo},
} = getState()
const config = {
headers: {
Authorization: `Bearer ${userInfo.token}`,
},
}
const { data } = await axios.post(`/api/products`, {}, config)
dispatch({
type: 'PRODUCT_CREATE_SUCCESS',
payload: data
})
} catch (error) {
dispatch({
type: 'PRODUCT_CREATE_FAIL',
payload:
error.response && error.response.data.message
? error.response.data.message
: error.meessage,
})
}
}
productReducers.js:
export const productCreateReducer = (state = {}, action) => {
switch (action.type) {
case 'PRODUCT_CREATE_REQUEST':
return {loading: true}
case 'PRODUCT_CREATE_SUCCESS':
return {loading: false, success: true, product: action.payload}
case 'PRODUCT_CREATE_FAIL':
return {loading: false, error: action.payload}
default:
return state
}
}
alternatively when i try to populate the database from post-man using this code in productController.js it works fine with sample data:
const createdProduct = asyncHandler(async (req, res) => {
const product = new Product({
name: 'Sample Name',
description: 'Sample Description'
})
const createdProduct = await product.save()
res.status(201).json(createdProduct)
})
plus im getting POST ipadress/api/products 500 (Internal Server Error) in console
You can config your axios api service config to separate file and use axios
const request = axios.create({
// baseURL: 'https://mock-api.com',
baseURL: BASE_URL ,
timeout: 5000
})
request.interceptors.request.use(
config => {
// get token
if (// check your token) {
config.headers["Authorization"] = "Bearer ${your-token}"
}
return config
},
error => {
// Do something with request error
console.log(error) // for debug
Promise.reject(error)
}
)
// Can also config axios response interceptors to handle API error
Your redux action
import axiosInstance from './your-axios-config-path'
export const createProduct = (product) => async (dispatch, _getState) => {
try {
dispatch({ type: 'PRODUCT_CREATE_REQUEST' })
const response = await axiosInstance.post(`/api/products`, {...product})
dispatch({
type: 'PRODUCT_CREATE_SUCCESS',
payload: response?.data ?? {}
})
} catch (error) {
dispatch({
type: 'PRODUCT_CREATE_FAIL',
payload: // error message,
})
}
}
Alternatively, you can use Redux Toolkit, It much easier to setup store and using. It includes createAsyncThunk, RTK Query to handle side effect.

React Redux problem on dispatching on button

I have a button that dispatches an action to create a post, for some reason the request never proceeds and it fails. This is the action. I have constants that's why types is not on a string
export const createPost = () => async (dispatch, getState) => {
try {
dispatch({
type: POST_CREATE_REQUEST,
});
const {
userLogin: { userInfo },
} = getState();
const config = {
headers: {
Authorization: `Bearer ${userInfo.token}`,
},
};
const { data } = await axios.post(
`http://localhost:5000/api/posts`,
config
);
dispatch({
type: POST_CREATE_SUCCESS,
payload: data,
});
} catch (error) {
const message =
error.response && error.response.data.message
? error.response.data.message
: error.message;
// if (message === 'Not authorized, token failed') {
// dispatch(logout());
// }
dispatch({
type: POST_CREATE_FAIL,
payload: message,
});
}
};
It continues to the POST_CREATE_REQUEST but always errors out to the POST_CREATE_FAIL.
I tried using postman and it works fine, I think the problem is the createPost action can't seem to receive the token even though im logged in as an admin, I'm not sure.
This is the useSelector of the postCreate
const postCreate = useSelector(state => state.postCreate);
const {
loading: loadingCreate,
error: errorCreate,
success: successCreate,
post: createdPost,
} = postCreate;
and this is the useSelector of the user that is logged in, currently as an admin.
const userLogin = useSelector(state => state.userLogin);
const { userInfo } = userLogin;
Rewrite this code
const { data } = await axios.post(
`http://localhost:5000/api/posts`,
config
);
as
const res = await axios.post(
`http://localhost:5000/api/posts`,
config
);
const data = res && res.data
There is already values on my Controller at the backend and just needed to add brackets in the action
from this
const { data } = await axios.post(
`http://localhost:5000/api/posts`,
config
);
to this
const { data } = await axios.post(
`http://localhost:5000/api/posts`, {},
config
);

Strange in React Native not showing err

I have a strange situation with a React Native app.
The part of the code with problems is this:
const request = async (options) => {
const defaults = {baseURL: 'base URL'}
let token = await AsyncStorage.getItem('token');
console.log('this is logged')
if(token) {
console.log("this is logged")
const headers = {
'TokenAuth': token
}
Object.assign(defaults, headers: headers);
}
console.log('this is NOT logged anymore')
options = Object.assign({}, defaults, options);
};
The idea is that i can't see anywhere the javascript error.
The error is on Object.assign(defaults, headers);
Why i can't see it ?
Thank you.
This is the whole component:
import constants from './../constants/constants';
import axios from 'axios';
import { AsyncStorage } from 'react-native';
import * as Utils from '../configs/utils'
const request = async (options) => {
const defaults = {baseURL: constants.BASE_URL}
let token = await AsyncStorage.getItem('token');
if(token) {
const headers = {'TokenAuth': token}
Object.assign(defaults, {headers: headers});
}
options = Object.assign({}, defaults, options);
return axios(options)
.then(response => {
return response.data
} )
.catch( error => {
if (error.response.status == 401) {
Utils.deleteToken();
}
let errResponse = 'Bad Error'
throw errResponse;
});
};
export function getAllTodos() {
return request({method: 'get',
baseURL: constants.BASE_URL,
url: '/api/items',
})
}

Categories

Resources