Redux Post Request failed with status code 404 - reactjs

I am trying to do a request to my local host on my network in a redux app with axios.
here is the request code :
export function createAccount(userInfo){
return async (dispatch) => {
try {
const resp = await axios.post(`${BASE_URL}/signup`, userInfo);
localStorage.setItem('token', resp.data.token);
dispatch({ type: types.SIGN_UP });
} catch(err) {
console.log('Sign Up Error:', err.message);
}
}
}
And here is what error is displayed :
Sign Up Error: Request failed with status code 404

Another possible cause may be mismatch between the names of the sent parameters and the expected on the REDUX end (actions). Better provide the code for the reducers and the action index. In my case I got 404 on POST request and when I checked the Headers (under Network) I figured out that the Request Payload is empty. The reason was the following:
const data = {
linkIdCampaign,
linkIdMix
}
this.props.onAddLink(data);
on the front end part did not correspond to the:
return axios.post("http://localhost:5000/YOUR_URL", { newLink, newMix})
.then(response => {
in the actions index.

Related

axios not returning the status of called api if error in reactjs

I am using axios to make apis calls in react. If there is no token provided or token got expired server sends the 401 status. I want to check that status on reactjs side.
But if i check err object in catch the status field is null.
Here is the code
try {
MyService.getIntet(reqBody);
} catch (err) {
handleUnAuthorizedResponse(err);
}
on the error this shows this type of info.
In the service
import axios from "axios";
and the function
static getIntent(reqBody) {
const url = `${this.intentionBaseUrl}/process`;
const options = {
headers: {
"Content-Type": "application/json"
},
};
return axios
.post(url, reqBody, options)
.then((res) => res.data)
}
HOw can i handle 401?
The error you've logged does not have a status because the request ended in a Network Error, which is not a 401.
You could check if it's a CORS problem, or else.
Otherwise, to manage the 401, seems good to use the handleUnAuthorizedResponse passing the error that should contain:
const err = {
..., // other things like the request etc
code: 'ERR_BAD_REQUEST',
response: {
status: 401, // status code
statusText: 'Unauthorized',
data: {} // data if the server sends some, like error messages, etc
}
}

React Authentication - network error when verifying if user is logged in, via token in local storage

TL;DR: On production, our React app is throwing a network error when trying to verify whether a user is logged in, via a token from localstorage...
We're using Sentry for error tracking / reporting, and Sentry has now flagged a few times an error that we have been unable to recreate on our end:
and when we view the error in Sentry, we get some additional information, including a key breadcrumb pointing to our tokenIsValid post request:
Our react app calls tokenIsValid one-time in our top-level App.js file, and this request checks to see if a user was previously logged in (via a token saved in localstorage). Here's the useEffect from our App.js:
Edit: with error reporting added
router.post("/tokenIsValid", async (req, res) => {
try {
const token = req.header("x-auth-token");
if (!token) return res.json(false);
const verified = jwt.verify(token, process.env.JWT_SECRET);
if (!verified) return res.json(false);
const user = await User.findById(verified.id);
if (!user) return res.json(false);
return res.json(true);
} catch (err) {
// update: ive added Sentry error handling here
res.status(500).json({ error: err.message });
}
});
We followed this tutorial for react authentication with hooks. Everything seemed to work okay when we tested it, but now Sentry is alerting us of some errors as users try to sign up & log into our website.
Edit: Even though I've tagged this as a React + React Authentication problem, Network Error leads me to think the issue is related to our Node API simply not staying up, and users not being able to hit this endpoint in the Node API. This post hints at that... our Node API is deployed in a docker container using GCP's Cloud Run.
Also, maybe it's a cors issue, per this (last answer by Tiago), and I should add app.use(cors({origin: true, credentials: true})); when I call cors().
You may be facing issues due to the values returned and how you consume the returned value. With the below-refactored code, you can just check the authenticated key in the returned object, use the message key for human-readable status message, and use the error key for detailed error in the event of a 500 error.
// An authentication middleware, abstacted from the code within route controller
const authMiddlware = (req, res, next) => {
try {
// Get token from header
const token = req.header("x-auth-token");
if (!token) {
return res.status(401).json({
message: 'Token required'
});
}
// validate token
const { id } = jwt.verify(token, process.env.JWT_SECRET);
if (id) {
req.verified = {
id
};
return next();
} else {
return res.state(401).json({
message: 'Invalid token'
});
}
} catch (err) {
res.status(500).json({
error: err,
message: err.message
});
}
};
// Apply the auth middleware
router.post("/tokenIsValid", authMiddlware, async (req, res) => {
try {
const user = await User.findById(req.verified.id);
if (user) {
return res.status(200).json({
authenticated: true,
message: 'Authenticated successfully'
});
} else {
return res.state(401).json({
message: 'Invalid user'
});
}
} catch (err) {
res.status(500).json({
error: err,
message: err.message
});
}
});

Axios promise resolving on pre-flight request response which makes associated GET execute out of order with rest of app

Good day,
I am working on a React app that makes use of React-Redux (with Thunk) and Axios.
I have an action that I dispatch which makes an authenticated API call. Due to the fact that I have Authorization headers on a cross-origin request, there is a pre-flight request.
The problem that I have is that Axios seems to be running the .then() code once the pre-flight request returns rather than when the associated GET request returns. This results in the Reducer function updating state before the results of the API GET request return.
I have added some console.logs to give more details to illustrate the problem. As you can see the pre-flight request is sent in the first entry. The .then executes one the pre-flight request returns with 200. The action then fires off and the reducer updates the state. My app responds by re-rendering the container that was connected to Redux. The child components also then update. Then the GET request completes and returns with a 200. And at this point nothing further happens because the reducer was already updated in the prior .then() mentioned above.
The action code is shown below. I have not pasted all the other code in as there are a number of files and they are relatively big. If needed I can include those too.
export const updatePlotDataInit = (datasetName, tableName, xFieldName,
yFieldName, chartId, chartType, plotId, newDomainStartDbIndex, newDomainEndDbIndex) => {
console.log('[actions/plot.js.js] - [updatePlotDataInit] - [start of function]');
return dispatch => {
dispatch(updatePlotDataStart());
console.log('[actions/plot.js.js] - [updatePlotDataInit] - [just before api request]');
instance.get( // custom axios instance with extra auth header used here
`/v1/datasets/${datasetName}/tables/${tableName}/fields/data?xField=${xFieldName}&yField=${yFieldName}&chartType=${chartType}&domainStart=${newDomainStartDbIndex}&domainEnd=${newDomainEndDbIndex}`
)
.then(response => {
console.log('[actions/plot.js.js] - [updatePlotDataInit] - [in .then before updatePlotDataSuccess]');
// dispatch redux action for success case
const currentLevel = response.data.metaData.current_level
const data = response.data.queryData.data //schema is available too
//datasetId, tableId, xFieldId, xField, yFieldId, yField, chartId, plotIdVal, currentLevel, data
dispatch( updatePlotDataSuccess( plotId, currentLevel, data ) );
// console.log(response);
console.log('[actions/plot.js.js] - [updatePlotDataInit] - [in .then after updatePlotDataSuccess]')
})
.catch(error => {
console.log(error);
// dispatch redux action for failure case
dispatch(updatePlotDataFail(error));
})
}
};
I am not entirely sure but it seems that Axios is seeing the successful pre-flight response as suitable to resolve the promsie and hence the .then gets executed.
Does this seem to be the case? And if so how would I force Axios to wait for the GET/POST/PUT/etc to succeed before resolving the promise?
Any help is appreciated.
I know it is for long time ago, but I think it could be useful for others who find this issue similar to their problem, with no answer...
for me it was just because of a careless coding :D,
here is my response inceptor, I missed "return" before Promise.resolve(axios(originalRequest));
I solved it by adding return :
AxiosInstance.interceptors.response.use(
(response) => {
return response;
},
function (error) {
const originalRequest = error.config;
let refreshToken = localStorage.getItem("refreshToken");
if (
refreshToken &&
error.response.status === 401 &&
!originalRequest._retry
) {
originalRequest._retry = true;
return axios
.post(apiUrl + `auth/refreshtoken`, { refreshToken: refreshToken })
.then((res) => {
if (res.status === 200) {
localStorage.setItem("accessToken", res.data.accessToken);
console.log("Access token refreshed!" + res.data.accessToken);
originalRequest.headers.Authorization = 'Bearer ' + res.data.accessToken;
//*************** I just return promise.resolve *****************//
return Promise.resolve(axios(originalRequest));
}
}).catch((error) => {
console.log(error);
});
}
return Promise.reject(error);
}

How to fix this function to handle different error type of error catching

I have developing mern stack web site. In that I have added below codes to handle logging.
onSubmit(e) {
e.preventDefault();
const obj = {
user_name: this.state.user_name,
password: this.state.password
};
axios.post('http://localhost:4000/login', obj)
.then(res=> localStorage.setItem('token',(res.data.token))
//localstorage.setItem('username','res.data.user.username)
)
}
When I click on login button this onSubmit() function called and will save token in local storage.
But, res.data have more details. (from backend it passes logged users information too)
So I want to add those to local storage. I tried that as commented in above function. It says error in res. Note : I user react for frontend.
Also I want to handle handle errors in any cases axios.post() didn't work as planned. In server side it send different messages for unmatched credentials and wrong passwords. How can I show those in my page. Thank you.
Since the only accepted data type in localStorage is string, you should stringify it first using JSON API.
const userDataStr = JSON.stringify(res.data);
localStorage.setItem('userData', userDataStr);
Now if you want to access the userData from localStorage you just need to convert it back to javascript object.
const userDataStr = localStorage.getItem('userData', userData);
const userData = JSON.parse(userDataStr);
You can have multiple catch in the returned promise of axios.post
axios.post()
.catch((error) => { })
.catch((error) => { })
But those catch will called with the same error so you need to handle it differently in each catch
Another suggestion:
If you want to easily handle the error, you can use higher order function like this
const handleError = (status, callback) => (error) => {
if (status === error) {
callback(error);
}
}
axios.post()
.catch(handleError(404, (error) => { /* only called when status === 404 */ }))
.catch(handleError(500, (error) => { /* only called when status === 500 */ }))

Automatic handle 401 response with redux-saga and fetch

I'm building a "secured" application and using redux-saga together with fetchjs for doing the async calls to the backend.
My backend returns a 401 status code when the user is not authorized, i want to catch this "exception" globally and dispatch a action so my react application goes to the login screen.
I found the following solution: https://github.com/redux-saga/redux-saga/issues/110, but in this case the handling for the 401 should be explicit in every saga that we build.
By adding code to every saga it becomes more complex. It also increases the chances a developer forgets to add the code for handling the 401 code.
Is there a nice way to handle this 401 response globally?
I would not use redux-saga since it does not have ability to do what you require.
Instead, when setting up store, API layer and other things configure API layer do invoke handler on every error occurred.
Sample of API layer that reports invokes error handler.
const conf = {
onError: () => {},
}
api.onError = (cb) => {
conf.onError = cb;
}
api.get = (url) => {
fetch(url)
.then(response => {
if (response.ok === false) {
return conf.onError(response);
}
return response;
})
// Network error
.catch(conf.onError)
}
Configure application.
import store from './store';
// Configure your API wrapper and set error callback which will be called on every API error.
api.onError((error) => {
store.dispatch({
type: 'API_ERROR',
payload: error,
});
});
// In you reducers...
isAuthorized(state, action) {
if (action.type === 'API_ERROR' && action.payload.statusCode === 401) {
return false;
}
return state;
}
Then, call API as usually, If error occurs, action is dispatched to store and you may or may not react to this actions.

Resources