React app on Heroku cannot make a POST request - node.js

I+m playing with the Chatkit API, and when running a React app in my local machine everything seems to work fine, but when I pushed it to Heroku, every time it tries to do a POST request through the server, it gives Failed to load resource: net::ERR_CONNECTION_REFUSED and index.js:1375 error TypeError: Failed to fetch
This is my server.js
const express = require('express')
const bodyParser = require('body-parser')
const cors = require('cors')
const Chatkit = require('#pusher/chatkit-server')
const app = express()
const chatkit = new Chatkit.default({
instanceLocator: I HAVE MY INSTANCE LOCATOR HERE,
key: I HAVE MY KEY HERE,
})
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
app.use(cors())
app.post('/users', (req, res) => {
const { username } = req.body
chatkit
.createUser({
id: username,
name: username
})
.then(() => res.sendStatus(201))
.catch(error => {
if (error.error === 'services/chatkit/user_already_exists') {
res.sendStatus(200)
} else {
res.status(error.status).json(error)
}
})
})
app.post('/authenticate', (req, res) => {
const authData = chatkit.authenticate({ userId: req.query.user_id })
res.status(authData.status).send(authData.body)
})
const PORT = 3001
app.listen(PORT, err => {
if (err) {
console.error(err)
} else {
console.log(`Running on port ${PORT}`)
}
})
And then this is my App.js
import React, { Component } from 'react'
import UsernameForm from './components/UsernameForm'
import ChatScreen from './ChatScreen'
class App extends Component {
constructor() {
super()
this.state = {
currentUsername: '',
currentScreen: 'WhatIsYourUsernameScreen'
}
this.onUsernameSubmitted = this.onUsernameSubmitted.bind(this)
}
onUsernameSubmitted(username) {
fetch('http://localhost:3001/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ username }),
})
.then(response => {
this.setState({
currentUsername: username,
currentScreen: 'ChatScreen'
})
})
.catch(error => console.error('error', error))
}
render() {
if (this.state.currentScreen === 'WhatIsYourUsernameScreen') {
return <UsernameForm onSubmit={this.onUsernameSubmitted} />
}
if (this.state.currentScreen === 'ChatScreen') {
return <ChatScreen currentUsername={this.state.currentUsername} />
}
}
}
export default App
I believe that it's at this time that it breaks
return <UsernameForm onSubmit={this.onUsernameSubmitted} />
When submitting it is expected to make a POST request to create a new user, and React to load the new component, but it just stays in the UsernameForm component, and in the console I can see these errors:
Failed to load resource: net::ERR_CONNECTION_REFUSED
index.js:1375 error TypeError: Failed to fetch

Probably the issue is the localhost in the endpoint at onUsernameSubmitted. We need more details about how your application is deployed and how the communication between server and spa is designed. If you have an Nginx you can set the redirect there.

I see three potential reasons of the error:
Database has to be well deployed and db:migrate triggered to define the db schema.
If 1) is fulfilled, then make sure whether your graphql path points to server url my-app.herokuapp.com not to localhost:<port>, The easiest way to check that is via browser/devtools/network query.
(optional) I use ApolloClient and my rule process?.env?.NODE_ENV ? 'prod_url' : 'dev_url' didn't work because of missing vars definitions in webpack:
new DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify(process.env.NODE_ENV),
},
}),```

Related

Can't send FormData to NodeJS server in MERN Stack App with TypeScript

I'm stuck with that request already. I'm trying to send FormData to NodeJS server but all I got in backend when I console.log the req.body is empty object. I checked the FormData keys/values and it's all good.
Here is my POST request in frontend:
const createProduct = (e: any) => {
e.preventDefault();
const data = new FormData()
data.append("name", name)
data.append("description", description)
data.append("price", price)
for (const colorAndImage of colorsAndImages) {
data.append('images', colorAndImage.images[1]);
data.append('colors', colorAndImage.colors);
}
data.append("type", type)
for (var pair of data.entries()) {
console.log(pair[0]+ ', ' + pair[1]); // the keys/values are correct
}
fetch('http://localhost:4000/products/create', {
method: 'POST',
body: data
})
.then(response => {
if (response.status === 201) {
setName('')
setDescription('')
setPrice('')
setType('')
} else if (response.status === 500) {
console.log('error');
}
})
.catch(error => console.log(error));
}
And my controller in backend:
productController.post('/create', async (req: Request, res: Response) => {
console.log(req.body)
try {
const data = {
name: req.body.name,
description: req.body.description,
price: req.body.price,
colors: req.body.colors,
images: req.body.images,
type: req.body.type,
likes: req.body.likes
}
let product = await create(data)
res.status(201).json(product)
} catch (error) {
console.log(error);
//res.status(500).json({error: error})
}
})
Even that I obviously send some data, the req.body is an empty object and I got that error:
Error: Product validation failed: name: Path 'name' is required.,
description: Path 'description' is required., price: Path 'price' is
required., type: Path 'type' is required.
at ValidationError.inspect
UPDATE
My express config:
import express, { Application } from 'express';
import cookieParser from 'cookie-parser';
import cors from 'cors';
import auth from '../middlewares/auth';
const corsConfig: cors.CorsOptions = {
credentials: true,
origin: ['http://localhost:3000', 'http://localhost:2000']
}
export default function (app: Application) {
app.use(cors(corsConfig))
app.use(cookieParser());
app.use(express.urlencoded({ extended: false }));
app.use(express.json())
app.use(auth())
}
And root server:
import express, { Application } from "express";
import routes from './routes'
import config from './config/config'
import mongooseConfig from './config/mongoose'
import expressConfig from './config/express'
const app: Application = express()
expressConfig(app);
mongooseConfig();
app.use(express.json())
app.use(routes)
app.listen(config.PORT, () => console.log(`Server is listening on port ${config.PORT}`))
Routes file:
import { Router } from "express";
import authController from "./controllers/authController";
import productController from "./controllers/productController";
const routes = Router()
routes.use('/auth', authController)
routes.use('/products', productController)
export default routes;
Maybe you can just submit it as JSON instead of Form data, this works always :smile:
const createProduct = (e: any) => {
e.preventDefault();
const data = {
"name": name,
"description": description,
"price": price,
"colorsAndImages": colorsAndImages,
"type": type,
};
// Please check mappings as I just transferred what you had :smile:
fetch('http://localhost:4000/products/create', {
method: 'POST',
body: JSON.stringify(data),
})
.then(response => {
if (response.status === 201) {
setName('')
setDescription('')
setPrice('')
setType('')
} else if (response.status === 500) {
console.log('error');
}
})
.catch(error => console.log(error));
}

React web application proxy

I am creating a simple web application. I have a problem, in the App.js file I have a function called Submit which calls a POST function with AXIOS when i press a button
componentDidMount() {
axios.get("/get")
.then((response) => {
this.setState({
fetchData: response.data
})
})
//this.Get().then((response)=>{ console.log("sono qui")})
}
submit = () => {
axios.post(`/insert`, this.state)
.then(() => { alert('success post') })
console.log(this.state)
document.location.reload()
}
I have another file called setupProxy.js where I direct these calls to the server
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
app.use(createProxyMiddleware('/get', { target: "http://localhost:3001" }));
app.use(createProxyMiddleware('/insert', { target: "http://localhost:3001"}));
};
The problem is that the server fails to enter the POST call while the GET call manages to enter quietly. Where am I wrong?
app.use(cors())
app.use(express.json())
app.use(express.urlencoded({ extended: true }));
app.post('/insert',(req,res)=>{
console.log(req.body.setBookName);
let options = {
url: 'http://backend.default.svc.cluster.local',
form: {
setBookName:this.state.setBookName ,
setReview: this.state.setReview
}
};
request.post(options);
})
app.get('/get',(req,res)=>{
console.log("Entro");
request.get("http://get-server.default.svc.cluster.local").pipe(res);
})
app.listen('3001', () => {console.log("Listening") })
The app.post code doesn't generate a response for the client.
request.post(options);
Maybe you need to pipe the response like the .get request?
request.post(options).pipe(res);

Express Session is not working with my localhost React Native App but work fine with Postmon

The problem is that when i login from postman all routes work correctly and express-session also working but when i login from my expo react native app it show cors error.
i also use axios.defaults.withCredential = true but not work.
Please give me solution if possible
OUTPUT
Postman
here login successfull
Here assignment route also work correctly
React Native App
Here when i make http request from react-native app it show this error
CODE
Expo React Native app:
config.js
import axios from 'axios';
const URL = [
'http://localhost:5000/lms',
'https://lms-assignments-tracker.herokuapp.com/lms',
];
axios.defaults.baseURL = URL[0];
axios.defaults.withCredentials = true;
export default axios;
Redux code work perfectly
userAction.js
import {
GET_ASSIGNMENT_RECORD,
} from './types';
export const getAssignment = () => (dispatch) => {
dispatch({
type: LOADING_ASSIGNMENT,
});
axios
.get('crawler/assignment')
.then((data) => {
dispatch({
type: GET_ASSIGNMENT_RECORD,
payload: data.data,
});
})
.catch((err) => {
if (err.response) {
// The request was made and the server responded with a status code
// that falls out of the range of 2xx
console.log(err.response.data);
console.log(err.response.status);
console.log(err.response.headers);
} else if (err.request) {
// The request was made but no response was received
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
// http.ClientRequest in node.js
console.log(err.request);
} else {
// Something happened in setting up the request that triggered an Error
console.log('Error', err.message);
}
console.log(err.config);
});
};
Screen Component Where i dispatch my action
Home.js
import {getAssignment} from '../redux/action/dataAction';
class Home extends Component {
constructor(props) {
super(props);
this.props.getAssignment();
}
//...
}
/**
* Redux Action
** /
const mapDispatchToProps = (dispatch) => {
return bindActionCreators(
{
logout,
auth,
getAssignment,
},
dispatch,
);
};
export default connect(mapStateToProps, mapDispatchToProps)(Home);
Node.js Code
index.js
//all imports are ok imports
const app = require('express')();
const session = require('express-session')
const cors = require('cors')
app.use(cors());
app.use(
session({
secret: 'Bukc AK',
resave: true,
saveUninitialized: true,
cookie: {
maxAge: 1000 * 60 * 60, // (1000 -> msec * 60 -> sec * 60 -> min * 24 -> hrs * 1 -> days)
},
}),
)
app.get('/lms/crawler/assignment',auth, (req,res) => {
...
}
login route
this route work perfectly give response { loginSuccess: true, userId: ... }
app.post('/lms/users/login',(req,res) => {
...
user.generateToken((err, user) => {
if (err) return res.status(400).send(err)
//here i set session.w_auth
req.session.w_auth = user.token
res.status(200).json({
loginSuccess: true,
userId: user._id,
})
})
}
here session.w_auth not get value
auth.js
let auth = (req, res, next) => {
let token = req.session.w_auth;
// here token result is undefined
console.log(token)
....
next()
})
}
module.exports = { auth }
Based on the comments, it sounds like you have a problem with preserving or sending the cookie. You can start by changing this:
axios.defaults.withCredential = true
to this:
axios.defaults.withCredentials = true
to use the proper spelling for that property.

Fetch API failed to Fetch during authentication, alongside CORS error

I have a button that lauches a fetch to my API that uses KOA and JWT. The javascript for the fetch initiated on click is:
<script>
function loginButton(user, pass) {
fetch('http://localhost:5454/api/login', {
method: "post",
headers: {
'Content-Type': "application/json"
},
body: JSON.stringify({
username: user,
password: pass
})
})
.then( (response) => {
console.log("Success")
})
.catch(e => console.log(e));
}
</script>
The code for my Authentication is:
router.post(`${BASE_URL}/login`, async (ctx) => {
const reqUsername = ctx.request.body.username
const reqPassword = ctx.request.body.password
const unauthorized = (ctx) => {
ctx.status = 401
ctx.body = {
error: 'Invalid username or password'
}
}
let attemptingUser
try {
attemptingUser = await Employee.findOne({ where: { username: reqUsername }})
if (attemptingUser != null && attemptingUser.password === reqPassword) {
ctx.status = 200
ctx.body = {
username: attemptingUser.username,
given_name: attemptingUser.given_name,
role: attemptingUser.role,
created_at: attemptingUser.createdAt,
updated_at: attemptingUser.updatedAt,
}
const token = jwt.sign({ username: attemptingUser.username, role: attemptingUser.role }, SECRET)
ctx.set("X-Auth", token)
} else {
unauthorized(ctx)
}
} catch(err) {
console.error(err)
console.error(`Failed to find username: ${reqUsername}`)
unauthorized(ctx)
}
})
The code for my KOA initiation is:
require('dotenv').config()
const Koa = require('koa')
const Router = require('koa-router')
const bodyParser = require('koa-bodyparser')
const baseRoutes = require('./routes')
const cors = require('#koa/cors');
const PORT = process.env.PORT || 8080
const app = new Koa()
app.use(bodyParser())
app.use(baseRoutes.routes())
app.use(cors());
app.listen(PORT, () => {
console.log(`Server listening on ${PORT}`)
})
Im using Port 8080 for my http-server and port 5454 for my npm server. I am getting a Failed to Fetch in the catch of the Fetch, as well as a CORS error related to not having a Access-Control-Allow-Origin header in the response header. I've tried a couple things and am ready to have a new set of eyes look at it, any tips?
Edit: I am successfully receiving the token in the X-Auth header, but for some reason it’s still throwing errors and I’d like to get them resolved before it spirals out of control.

Ionic/Angular change Data in Node Server

I have create a Node application that uses the Twit(twitter api) to allow my ionic/Angular Application to post a tweet on twitter, however this problem that I have is that i get a 404 error message when I set the REST method to Post, it seems to work with a GET method.
However I do not know how I can dynamically change the Data in my node application from my Ionic Application.
I want to change the User's information and the Message that is being sent, but I do not know where to start. if anyone can guide me that will be appriecated.
this is my Node server.js file
const express = require('express');
const Twitter = require('twit');
const app = express();
const client = new Twitter({
consumer_key: '...',
consumer_secret: '...',
access_token: '...',
access_token_secret: '...',
});
app.use(require('cors')());
app.use(require('body-parser').json());
app.post('/post_tweet', (req, res) => {
tweet = {status:"Random"};
client
.post(`statuses/update`, tweet)
.then(timeline => {
console.log(timeline);
res.send(timeline);
})
.catch(error => {
res.send(error);
});
});
app.listen(3000, () => console.log('Server running'));
this is my twitter service in my Ionic application
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { map } from 'rxjs/operators';
#Injectable({
providedIn: 'root'
})
export class TwitterserviceService {
api_url = 'http://localhost:3000';
constructor(private http: HttpClient) { }
tweet(tweetdata: string) {
return this.http.get<any>(`${this.api_url}/post_tweet`)
.pipe(map(tweet => {
alert("tweet posted")
return tweet;
}));
}
}
and this is the method that I use to send a Post, however the message "this works" doesent post instead the default message in the Node application is sent "random"
sendTweet() {
this.api.tweet('this works')
.pipe(first())
.subscribe(
data => {
console.log('yes')
},
error => {
'failed'
});
}
Your service should do a POST, not a GET. And a POST must have a body.
tweet(tweetdata: string) {
return this.http.post<any>(`${this.api_url}/post_tweet`, { tweetdata })
}
note that you will have to handle this body in the express route and probably do something with this tweetdata attribute.
Alright I have found the answer and it was actually quite simple
here it the link to the resource that i am using => https://code.tutsplus.com/tutorials/connect-to-the-twitter-api-in-an-angular-6-app--cms-32315
this is my node js code
const express = require('express');
const Twitter = require('twit');
const app = express();
const client = new Twitter({
consumer_key: '...',
consumer_secret: '...',
access_token: '...',
access_token_secret: '...',
});
app.use(require('cors')());
app.use(require('body-parser').json());
app.post('/post_tweet', (req, res) => {
tweet = req.body;
client
.post(`statuses/update`, tweet)
.then(tweeting => {
console.log(tweeting);
res.send(tweeting);
})
.catch(error => {
res.send(error);
});
});
app.listen(3000, () => console.log('Server running'));
and here it the code that I have in my Ionic/Angular Project
api_url = 'http://localhost:3000';
tweet(tweetdata: string) {
return this.http.post<any>(`${this.api_url}/post_tweet/`, {status: tweetdata})
.pipe(map(tweet => {
alert("tweet posted")
return tweet;
}));
}
sendTweet() {
this.tweet('This is app code')
.pipe(first())
.subscribe(
data => {
console.log('yes')
},
error => {
'failed'
});
}
hope this helps someone.

Resources