React Application form cannot POST to my backend api - node.js

I have already created a backend api with node and express which works great, through Postman and Insomnia, but for some reason my create function wont post to my api. It can login to the API fine, and the form is returned with each user inputted field, but the issue relates to somewhere after axios.post, as if i put in the incorrect url it throws a 404, but if i put in the correct url it doesnt throw any error but completely skips over the .then(response function and goes straight to console.log(3). Any ideas or help relating to this would be great, Thanks!
Imports
import {useState} from 'react'
import axios from 'axios'
import {TextField, MenuItem, FormControl, Select, InputLabel, Button, Checkbox} from '#mui/material'
import { useNavigate } from 'react-router-dom'
Submit form code
const submitForm = () => {
console.log(form)
let token = localStorage.getItem('token')
console.log(1)
axios.post('http://localhost:9000/miniatures/create', form,{
headers: {
"Content-Type": "application/json",
"Authorization": `jwt ${token}`
}
})
.then(response => {
console.log(2)
console.log(response.data)
navigate(`/miniatures/${response.data._id}`)
})
.catch(err => console.log(err))
console.log(3)
}

React likely does not know how to proxy API requests to the Express server.
In package.json for the front end, try adding:
"proxy": "http://localhost:9000",
Then, make your post request to (something like) axios.post(/miniatures/create). The exact path will depend on how you structured your Express routes. It could be something like /api/miniatures/create.
In development, the development server will recognize that it’s not a
static asset, and will proxy your request.

Related

React + Nodejs : Share code between Front and Back End

I have a front-end built in React and Backend built in Nodejs (framework Adonisjs). I want to share some code between The Client and the Server. My Team can't use NPM or GitHub to do it, because of Company Policies.
Reading NPM docs, I found a possible solution:
On package.json I included the following line in "dependencies" entry:
"sharedCodeModule": "index.js:../<sharedCodeFolder>"
Doing that, I could import the module in both Front and Backend. The thing is that I've never seen such solution for this problem (not that I searched a lot). Anyone can see any problems in this approach?
Ps: Sorry for bad English. Not a native speaker.
Not sure I understand the question, yet, if your backend is perfectly set to make post and get requests, your front end should only take call your backend funcionalities.
Try to use npm axios , and you can have a example.js file like:
import axios from 'axios';
export default axios.create({
baseURL: 'http://127.0.0.1:8000/'
})
where you switch that baseURL for what you actually need. And then on your frontend you should have axios post and get requests, for example, you either import the above file in the file of the frontend component and do the post/get like:
import axiosFunc from "./example";
class WhateverComp extends Component {
constructor(props) {
super(props);
this.state = {
(...)
};
}
(...)
handleSubmit = async () => {
const response = await axiosFunc.post("/yourEndPointHere", {
exampleParam: this.state.param
});
message.success("success.");
};
(...)
Or, as you can see in the link I gave you, with axios, you make call it directly and do your requests like the example below:
axios.post('/user', {
firstName: 'Fred',
lastName: 'Flintstone'
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
Again, I'm not sure I understood what you actually want to do, I hope axios helps you.

CORS Error in a working setup while trying to authenticate using Google+ API in React/Node setup

I was implementing the Oauth2.0 authentication using Google. I used react-google-login npm on the frontend to authenticate the user using Google Oauth2.0. I successfully created the CLient-id and secret under google cloud platform for my project, along with the URI as needed.
The frontend is running on default localhost:3000 and backend (node/express) running on localhost:9001 with proxy enabled on frontend to redirect the request to backend.
I was able to authenticate using Google more than 2 dozen times last night as i was working on the backend siginIn contoller. I was also able to add the user to my Mongodb after successful authentication from Google.
All of a sudden, i was getting CORS error which is a bit strange as none of the code or Google configs were changed.
My Google config looks as follows.
My code on the frontend is still successfully redirecting the user to Google for authentication. Its also generating the right google credentials.
SignIn Component Code snippet passing the info to responseGoogle which resides in withLogin HOC Parent Component.
<GoogleLogin
clientId={GOOGLE_CLIENT_ID}
buttonText="Google"
render={(renderProps) => (
<button onClick={renderProps.onClick} style={customStyle}>
<img className="googleBtn" src={googleIcon} alt="GMAIL ICON" />
</button>
)}
onSuccess={responseGoogle}
onFailure={responseGoogle}
cookiePolicy={"single_host_origin"}
/>
withLogin HOC Parent Component dispatching the info to Redux thunk.
const responseGoogle = (res) => setGoogleResp(res);
useEffect(() => {
googleResp?.error &&
setValues({ ...values, serverError: "GOOGLE LOGIN FAILED" });
googleResp?.tokenId && dispatchGoogleSignInDataToBackend()
}, [googleResp]);
const dispatchGoogleSignInDataToBackend=async ()=>{
const data=await dispatch(allActions.googleSignInAction(googleResp,whoLoggedIn));
if (data.error) {
setValues({ ...values, serverError: data.error, success: false });
} else {
const {
email,
name,
_id,
role,
listOfEmailOfAllClientsForLawyerLogin,
} = data.userCred;
saveJwtToLocalStorage(
data.token,
{ name, email, _id, role, listOfEmailOfAllClientsForLawyerLogin },
() => {
setValues({
email,
serverError: false,
success: true,
});
}
);
}
}
I am sending the appropriate CORS header in the request to the backend.
export const dataHeaders = {
"Access-Control-Allow-Origin": "*",
"Content-Type": "application/json",
"Access-Control-Allow-Headers" :"*"
};
Redux thunk code:-
export const googleSignInAction=(googleResp,whoLoggedIn)=>{
console.log("Login Success: currentUser:", googleResp);
return async (dispatch) => {
dispatch({ type: SIGNIN_LOADING });
try {
const response = await axios.post(
`${API_URL}/googlesignin`,
{
googleResp,
whoLoggedIn
},
{
headers: dataHeaders,
}
);
console.log("response inside googleSignInAction", response);
// CHANGED COZ OF ESLINT WARNING.
if (
response.status === 201 &&
Object.keys(response.data).includes("token") &&
Object.keys(response.data).includes("userCred")
) {
dispatch({ type: SIGNIN_SUCCESS, data: response.data });
return response.data;
} else {
dispatch({ type: SIGNIN_FAILED });
}
} catch (error) {
dispatch({ type: SIGNIN_FAILED });
return error.response.data;
}
};
}
API URL Points to following:-
export const API_URL="http://localhost:9001/api";
No request is reaching the backend because of CORS error.
Frontend receiving the Correct Response from Google Post authentication.
Errors on the Frontend.
Browsers will first send a pre-flight request to check CORS. In your backend code, you have to allow the front-end host and port. In this case localhost:3000.
The reason you are getting the cors error is bacause its on two different ports.
But if proper cors response is given by backend (port 9000), it will resolve.
Clearing the browser cookies and cache made everything work again. googlesignin is working without cors error. I have added following line of code to serve all static files from backend to frontend.
app.use(express.static(path.join(__dirname, '../frontend/public')));

Angular 2+ http.get() stuck in pending status

I have a MEAN app.
Angular CLI: 7.1.4
Node: 10.1.0
OS: win32 x64
Angular: 7.1.4
recently the http requests from HttpClientModule have been getting stuck and not posting to the node server:
Img of chrome dev tools xhr pending request
The nodejs server ( running locally and in production (azure web app) does not indicate that it ever received the request. This happens inconsistently. some times it completes other times it just hangs.
Here is a snippet of a testConnection call from Angular to the server:
Angular service
import { Injectable } from '#angular/core';
import { HttpClient, HttpErrorResponse } from '#angular/common/http';
import { throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { environment } from '../../environments/environment';
const Headers: any = { withCredentials: true, responseType: 'json', headers: { 'Content-Type': 'application/json' } };
#Injectable({
providedIn: 'root',
})
export class UserService {
constructor(private _http: HttpClient) {}
loginStatus() {
return this._http.get(`${environment.serverURL}/api/login-status`, Headers).pipe(catchError(this.handleError));
}}
Angular Component:
ngOnInit() {
this._userSvc.loginStatus().subscribe(
(result:any)=>{console.log(result)},
(error:any)=>{console.log(error)})
}
Node/express:
router.get('/login-status', (req, res, next) => {
if (req.isAuthenticated()) {
res.status(200).json(req.user);
} else {
res.status(403).json({
success: false,
error: 'User not Authenticated',
message: "Please return to the login in page and try again."
})
}
})
Node is using passport to authenticate
Don't get tied up with the passport issue because its not always this route that fails. I have simple routes that do no validation and just return some text that fail too.
I tried modifying my CORS options but I've only managed to block myself.
There are times when restarting the server will allow the request to finish but not always.
I found the problem and i'm embarrassed to say it was in the SQL connection string for mssql.
I had ((config,error)=>{}) instead of the correct (config,(err)=>{}); This was in the de-serialize user function of passport. Nothing like looking over thousands of lines of code to spot one little problem.

Cannot get cookie in middleware with node and angular

I am using nodejs, express, cookie-parser and angular 6. Right now angular runs in http://localhost:4200 and node/express in http://localhost:3000. I also put
const cors = require('cors');
app.use(cors());
in my app.js in node, so both angular and node can communicate.
In my login route I create an http-only cookie with the token and then I send back a JSON with some info and the user id
res.cookie("SESSIONID", token, {httpOnly:true, secure:true});
res.json({ success:true, msg:'you are logged in', userid: resolved.id});
I suppose that the SESSIONID cookie is send with every request back to the server , so I dont have to set it myself before every request
In my middleware, I want to get the token from the cookie in order to check it. So, I do
const token = req.cookies.SESSIONID;
console.log('token from validate : ', token);
//check token and expiration, either next(); or redirect back
in my routes I have
router.get('cms/account', myMiddleware.required(), (req, res)=>{
res.json({ msg:'profile data'});
});
My profile service contacts the account route of node
import { Injectable } from '#angular/core';
import { Http, Headers } from '#angular/http';
import { map } from "rxjs/operators";
#Injectable({
providedIn: 'root'
})
export class ProfileService {
constructor(private http:Http) { }
getProfile(){
return this.http.get('http://localhost:3000/cms/account').pipe(map(res => res.json()));
}
}
my profile service should render some profile data
import { Component, OnInit } from '#angular/core';
import { ProfileService } from '../../services/profile.service';
#Component({
selector: 'app-profile',
templateUrl: './profile.component.html',
styleUrls: ['./profile.component.css']
})
export class ProfileComponent implements OnInit {
constructor( private profileService: ProfileService) { }
ngOnInit() {
this.profileService.getProfile().subscribe((data) =>{
console.log('profileService -- ', data);
})
}
}
After I login I go to http://localhost:4200/cms/profile. In the console I see token from validate : undefined
So I am sure that angular successfully reaches until the validation middleware, but cannot get the cookie.
I fail to understand why the cookie is not there. Is it my synatx? Is it not set at the start? Should I include it with every request ? Is it the different ports in localhost ? I gave as much details I could, if you need extra, just tell me. Please help me debug this, because I am lost.
Thanks

How to manage authentication of a user through a vue router and a server-provided JWT token?

I am building a web app using vue/webpack for the front end and node.js/express on back end. The node.js back end is exposing REST APIs that are used by the front end to login, logout and other CRUD-like operations.
On server side, the login REST API is setting a JWT token and redirects to the vue application home path.
On front end side, the vue components access (including home) is guarded by the beforeEach method of the vue router (based on sample from here).
My question is, from within my vue application, how can I access the JWT token (set by the login REST API in the HTTP Headers of the response) and store it in my vuex store so that my vue components can use it?
Thanks for your help!
PS: I am using node.js 8.5, Vue 2.4.4, Vue Router 2.7, Vuex 2.4.1
Use Axios Interceptors:
import { defaults, get } from 'lodash';
import axios from 'axios';
import store from 'vuex-store';
import def from './default';
export const connection = (options = {}) => {
def.headers = { Authorization: store.getters.auth.getToken() };
const instance = axios.create(defaults(def, options));
instance.interceptors.response.use(
function (response) {
const newtoken = get(response, 'headers.authorization');
if (newtoken) store.dispatch('setToken', newtoken);
console.log(response.data);
return response;
},
function (error) {
switch (error.response.status) {
case 401:
store.dispatch('logoff');
break;
default:
console.log(error.response);
}
return Promise.reject(error);
}
);
return instance;
};

Resources