I've created a little React/Node app and I want to send a certain piece of data from the React frontend to the Node backend. The data is based on what you type in an input and saved as a state inputCardHolder, I want to now send that data to the other file, which is non-React, to be used there.
How would I do this?
App.js(React)
import React, { useState } from 'react';
import axios from 'axios'
import './App.css';
function App() {
const [cardHolder, setCardHolder] = useState("");
const [inputCardHolder, setinputCardHolder] = useState("");// This is the state I wanna send
const [cardNumber, setCardNumber] = useState("");
const [balance, setBalance] = useState("");
const [expDate, setExpDate] = useState("");
const [cvc, setCvc] = useState("");
function getCardData() {
axios.get("http://localhost:5000/", { crossdomain: true })
.then(response => {
setCardHolder(response.data.data.name_on_card);
setCardNumber(response.data.data.card_pan);
setBalance(response.data.data.amount + " " + response.data.data.currency);
setExpDate(response.data.data.expiration);
setCvc(response.data.data.cvv);
})
};
const handleInputChange = (event) => {
setinputCardHolder(event.target.value);
};
return (
<div>
<div className='vcard'>
<div className='theBalance'>
<h2>{balance}</h2>
</div>
<div className='numNcvc'>
<h2 className='theNum'>{cardNumber}</h2>
<h2 className='theCvc'>{cvc}</h2>
</div>
<div className='expNholder'>
<h2>Expiry Date<br/> {expDate}</h2>
<h2>Card Holder<br/> {inputCardHolder}</h2>
</div>
</div>
<div className='details-div'>
<form className='details'>
<input
placeholder='Name on Card'
type="text"
id='cardholder'
name='cardholder'
onChange={handleInputChange}
value={inputCardHolder}></input>
<input placeholder='Amount (in USD)' type="text"></input>
<input placeholder='MTN MoMo Number' type="text"></input>
</form>
<button className='createCardBtn' onClick={getCardData}>
Create Card
</button>
</div>
</div>
);
}
export default App;
nodecard.js(Node Backend)
const { response } = require('express');
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
const Flutterwave = require('flutterwave-node-v3');
const flw = new Flutterwave("FLWPUBK_TEST-63a79c5a6fe457d75a611b0f376e3e53-X", "FLWSECK_TEST-a6281194ef4ca095e794a1681fe32d69-X");
// Payload: Flutterwave Card Details
const payload = {
"currency": "USD",
"amount": 50,
"billing_name": "Daniel Odd",// I need the 'inputCardHolder' data to be here
"billing_address": "2014 Forest Hills Drive",
"billing_city": "React",
"billing_state": "NY",
"billing_postal_code": "000009",
"billing_country": "US",
}
flw.VirtualCard.create(payload)
.then(response => {
console.log(response);
app.use(function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
next();
});
app.get("/", (req, res) => {
res.send(response)
});
});
/*const wordy = "Another word"
app.use(function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
next();
});
app.get("/", (req, res) => {
res.send(wordy)
});*/
app.listen(5000, () => {console.log("Server started on port 5000")})
//createVcard();
Related
I am working on a stripe checkout project but got stuck when I was not able to redirect to the stripe checkout page because of the cors error. My react frontend is running at localhost 3000 and express backend at localhost 5000. Here is how I am setting headers and using cors in my server.js :
if (process.env.NODE_ENV === 'development') {
app.use(cors({
credentials: true,
origin: process.env.CLIENT_URL
}))
app.use(morgan('dev'))
}
app.use(function(req, res, next) {
res.setHeader("Access-Control-Allow-Credentials", true);
res.setHeader("Access-Control-Allow-Origin", "http://localhost:3000");
res.setHeader('X-Frame-Options', 'sameorigin');
res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, multipart/form-data");
res.setHeader("Access-Control-Allow-Methods", "HEAD,GET,POST,DELETE,OPTIONS,PUT");
next();
});
Here is my stripe.route.js :
const express = require('express')
const router = express.Router()
const Stripe = require('./../controllers/stripe.controller');
router.post('/checkout' , async(req,res) => {
const product = req.body.body;
console.log(product);
try
{
const session = Stripe.createCheckoutSession(product)
return res.send(session)
}
catch(e)
{
console.log(e);
res.status(400)
return res.send({
error: {
message: e.message
}
})
}
})
module.exports = router;
Here is my stripe.controller.js:
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY)
const createCheckoutSession = async(plan) => {
const session = await stripe.checkout.sessions.create({
success_url: `http://localhost:3000/success`,
cancel_url: `http://localhost:3000/fail`,
payment_method_types: ['card'],
line_items: [
{price: plan, quantity: 1},
],
mode: 'subscription',
});
return session;
}
module.exports = {
createCheckoutSession
}
Here is my react fronend page :
import React, { useRef } from "react";
import { isAuth } from "../helpers/auth";
import { useNavigate } from "react-router-dom";
import axios from 'axios';
import styles from "./Pricing.module.scss";
export const Pricing = () => {
const buttonValue = useRef();
const navigate = useNavigate();
const setBtnValue = (e) => {
buttonValue.current = e.target.value;
};
const checkoutHandler = async (e) => {
const btnValue = buttonValue.current;
console.log(btnValue);
const res = await axios
.post( 'http://localhost:5000/api/checkout' , {
method: "POST",
headers: {
"Content-Type": "application/json",
},
withCredentials: true,
credentials: 'same-origin',
body:
btnValue,
})
const url = res.url
window.location.href = url
};
return (
<div className={styles.container}>
<h2 className={styles.heading}>Choose</h2>
<div className={styles.priceRow}>
<div className={styles.priceCol}>
<p>Starter</p>
<h3>
50$ <span> / month</span>
</h3>
<ul>
<li>1 Website</li>
<li>10 GB Disk Space</li>
<li>Free Email Address</li>
<li>No SSL certificate</li>
<li>Limited Support</li>
</ul>
<form onSubmit={checkoutHandler}>
<button
value="price_1"
type="submit"
className="btn"
name="product"
onClick={setBtnValue}
>
Upgrade Now
</button>
</form>
</div>
</div>
</div>
);
};
you can send back session.url from backend , and then from front end you redirect using window.location.replace , and it will work
This is my express server
const express = require("express");
const app = express();
const mongoose = require("mongoose");
require("dotenv").config();
const cors = require("cors");
const userData = require("./db");
var PORT = process.env.PORT || 3001;
app.use(cors());
app.use(express.urlencoded({ extended: false }));
mongoose
.connect("mongodb://localhost", {
useNewUrlParser: true,
useUnifiedTopology: true,
})
.then(() => {
console.log("Connected to database!!");
})
.catch((e) => {
console.log("Error : " + err);
});
app.get("/", (req, res) => {
res.json({ server: "Running" });
});
app.get("/login", (req, res) => {
res.json({ user: "true" });
});
app.post("/signup", (req, res) => {
console.log(req);
res.redirect("/");
});
app.listen(PORT, () => {
console.log(`Server running at http://localhost:${PORT}`);
});
and this is my React component
import React, { useState } from "react";
import "./Signup.css";
import axios from "axios";
import { useSelector } from "react-redux";
import { selectAuth } from "../../features/authSlice";
export default function Login() {
const isAuthenticated = useSelector(selectAuth);
const [user, setUser] = useState("");
const [pass, setPass] = useState("");
const handleSignup = async (e) => {
e.preventDefault();
var bodyFormData = new FormData();
bodyFormData.append("username", user);
bodyFormData.append("password", pass);
const res = await axios({
method: "post",
url: "http://localhost:3001/signup",
data: bodyFormData,
headers: { "Content-Type": "multipart/form-data" },
});
};
return (
<div className="signup__container">
<h2>Signup</h2>
<form className="signup__form" autoComplete="off">
<div className="signup__imgContainer">
<img
src={require("../../assets/avatar-placeholder.jpg").default}
alt="Avatar"
className="signup__avatar"
/>
</div>
<div className="signup__inputContainer">
<label for="uname">
<b>Username</b>
</label>
<input
type="text"
placeholder="Enter Username"
name="uname"
onChange={(e) => setUser(e.target.value)}
required
/>
<label for="psw">
<b>Password</b>
</label>
<input
type="password"
placeholder="Enter Password"
name="psw"
required
onChange={(e) => setPass(e.target.value)}
/>
<button type="submit" onClick={handleSignup}>
Signup
</button>
<label>
<input type="checkbox" name="remember" /> Remember me
</label>
</div>
</form>
<div>{isAuthenticated.toString()}</div>
</div>
);
}
I am trying to post data using axios but I am unable to access this data in my backend. Am i doing it right, if yes then can anyone tell me what's wrong. and if no then how can I correct it to use the data.
I tried various things like sending the data as params but nothing worked on server it was always undefined however the console.log(req) gives something but I didn't see any of my post data in it.
add app.use(express.json());
if it does not work. then add body-parser in your package.
const express = require("express");
const bodyParser = require("body-parser"); // install body-parser
const cors = require("cors");
const app = express();
app.use(bodyParser.json({ limit: "50mb" }));
app.use(
bodyParser.urlencoded({
limit: "50mb",
extended: true,
parameterLimit: 50000,
})
);
app.use(express.json()); /// add
In the React app, you're using Content-Type multipart/form-data. When you use this Content-Type, the server needs to parse the request differently. This Content-Type is used when you want to upload a file in the request. It isn't the case here, so you should use Content-Type application/json instead.
Your request should be:
const res = await axios({
method: "post",
url: "http://localhost:3001/signup",
data: { username : user, password : pass},
headers: { "Content-Type": "application/json },
});
And in the Express application, you need to add a middleware to parse incoming requests in application/json Content-Type.
app.use(cors());
app.use(express.urlencoded({ extended: false }));
app.use(express.json()); // <---- add this
In the route, you can see the data inside req.body
app.post("/signup", (req, res) => {
console.log(req.body);
res.redirect("/");
});
Good day to all of you. I'm trying to build a log in and right now im struggling with the register form, I'm using react js for FrontEnd and nodejs/express for BackEnd.
I created the register form, I'm putting data from this register form inside an object, parsing it to a JSON obj and sending it to the node server through fetch api, however the cors thing is not letting this happen, i'm not sure why. The next is the code from the register(front side)
import React, { useState } from 'react';
import './Register.css';
import Title from './Title/Title';
import Label from './Label/Label';
import Input from './Input/Input';
function Register(){
const [ name, setName ] = useState('');
const [ lastname, setLastname ] = useState('');
const [ email, setEmail ] = useState('');
const [ username, setUsername ] = useState('');
const [ password, setPassword ] = useState('');
function handleChange(name, value){
if(name==='name')setName(value);
else if (name==='lastname')setLastname(value);
else if (name==='email')setEmail(value);
else if (name==='username')setUsername(value);
else if (name==='password')setPassword(value);
}
function handleSubmit(e){
e.preventDefault();
let account = { name, lastname, email, username, password };
if(account)console.log(account);
var url = 'http://localhost:3030/';
fetch(url, {
method: 'OPTION',
body: JSON.stringify(account),
headers:{
'Content-Type': 'application/json'
}
}).then(res => res.json())
.catch(error => console.error('Error:', error))
.then(response => console.log('Success:', response));
///////////////////////////////////////////////////////////////////////////////////
}
return(
<div className='register-div'>
<Title text='Register Form'/>
<div className='squareout'>
<div className='square'>
<Label text='Name'/>
<Input attribute={{type:'text', name:'name'}} handleChange={handleChange}/>
</div>
<div className='square'>
<Label text='Last Name'/>
<Input attribute={{type:'text', name:'lastname'}} handleChange={handleChange}/>
</div>
<div className='square'>
<Label text='E-Mail'/>
<Input attribute={{type:'text', name:'email'}} handleChange={handleChange}/>
</div>
<div className='square'>
<Label text='Username'/>
<Input attribute={{type:'text', name:'username'}} handleChange={handleChange}/>
</div>
<div className='square'>
<Label text='Password'/>
<Input attribute={{type:'password', name:'password'}} handleChange={handleChange}/>
</div>
</div>
<button className='boton' onClick = {handleSubmit}>Register</button>
</div>
)
};
export default Register;
and this is from the server side:
const express = require('express');
const app = express();
const port = 3030;
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})
app.use(express.static('public'));
app.use(function(req, res, next) {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,DELETE");
res.setHeader("Access-Control-Allow-Headers", "X-Requested-With, Access-Control-Allow-Headers, Content-Type, Authorization, Origin, Accept");
res.setHeader('Access-Control-Allow-Credentials', true)
next();
});
app.use(express.json());
app.post('http://localhost:3030/', (request, response) => {
console.log(request.body);
const data = request.body;
response.json({
name: data.name,
lastname: data.lastname,
email: data.email,
username: data.username,
password: data.password
})
});
and yet I'm getting this error:
Line 33: fetch(url, {
this is from the first code, the front side
Instead of reinventing the wheel, you can use CORS
And simply do:
const cors = require('cors')
const app = express()
app.use(cors())
Simply when facing an CORS issue remember these concepts,
It is not front-end apps fault (mostly)
you are trying to cross domain requests
those are blocked by default
You can allow this by allowOrigins with backend (syntax varies on language)
problem here is accessing localhost:3030 from localhost:3000
const express = require('express');
const cors = require('cors');
const app = express();
app.use(cors())
//for single origin
var corsOptions = {
origin: 'http://localhost:8080',
optionsSuccessStatus: 200 // For legacy browser support
}
app.use(cors(corsOptions));
source
If you set Access-Control-Allow-Credentials to true means you are allowing credentialed request
res.setHeader('Access-Control-Allow-Credentials', true)
Then you can't set Access-Control-Allow-Origin to *(wildcard)
res.setHeader("Access-Control-Allow-Origin", "*");
so solution here is that,
you have to set specific origin here,(frontend app origin for reactjs by default its http://localhost:3000/)
res.setHeader("Access-Control-Allow-Origin", "http://localhost:3000/");
In the end I found the solution, first instead of the method 'OPTION' I used 'POST' and the on the server side, i changed 'http://localhost:3030/' to just '/' and worked.
I am using ReactJS to create a simple sendMail app. And the problem is I do not receive req.file in my server (ExpressJS).
myForm.js
<form className="content-container mailing-form" encType='multipart/form-data'>
<h1>Let's see if it works</h1>
<div>
<label>Mail: </label>
<input type="text" value={this.state.email} onChange={this.handleChangeToMail} style={{ width: '50%' }} />
</div>
<div>
<label>Subject: </label>
<input type="text" value={this.state.subject} onChange={this.handleChangeSubject} style={{ width: '50%' }} />
</div>
<div>
<textarea
id="test"
name="test-mailing"
onChange={this.handleChangeFeedback}
placeholder="Post some lorem ipsum here"
required
value={this.state.feedback}
style={{ width: '100%', height: '150px' }}
/>
</div>
<div> //Here is my input file
<label>File: </label>
<input
type="file"
onChange={this.handleChangeFile}
name="myFile"
/>
<img src="" id="preview" alt="Image preview..."></img>
</div>
<input type="button" value="Submit" onClick={this.handleSubmit} />
</form>
handleChangeFile
handleChangeFile = e => {
e.preventDefault();
let fReader = new FileReader();
let file = '';
fReader.readAsDataURL(e.target.files[0]);
fReader.onloadend = (event) => {
document.getElementById('preview').src = event.target.result;
file = event.target.result;
this.setState(() => ({ file }));
console.log(this.state.file);
}
}
handleSubmit
handleSubmit = e => {
let formData = new FormData();
formData.append('name', this.state.name);
formData.append('email', this.state.email);
formData.append('feedback', this.state.feedback);
formData.append('subject', this.state.subject);
formData.append('file', this.state.file);
const config = {
headers: {
"Content-Type": "multipart/form-data",
"Accept": "application/json",
"type": "formData"
}
}
const url = "http://localhost:8081/send";
axios
.post(
url,
formData,
config
)
.then(res => console.log(res.data))
.catch(err => console.log('Error: ', err));
}
Server.js
const nodemailer = require('nodemailer');
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
var multer = require('multer');
const app = express();
const port = 8081;
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next(); });
app.get('/', (req, res) => res.send('......!'));
const storage = multer.diskStorage({
destination: './uploads',
filename: function (req, file, cb) {
cb(null, file.fieldname + Date.now());
} })
const uploads = multer({
storage: storage
}).single('myFile');
app.post('/send', uploads, (req, res) => {
if (req.file) {
res.send('Uploaded !');
} else {
res.send('Fail !!');
}
});
app.listen(port, () => console.log(`Example app listening on port ${port}!`));
And I keep receive "Fail !!" message on my form.
I have tried to add any solution I can find. I know it can be some mess in there, sorry for that :') !
I solved my problem, thanks to this thread : Convert Data URI to File then append to FormData
I add a function to convert file from weird base64 string to Blob type before send it to server. Then my server can receive req.file !!
1.make your uploads folder as static folder
app.use(express.static('uploads'));
2.change your destination like below
destination : function( req , file , cb ){
cb(null,'./uploads');
},
append your file as myFile in frontend
formData.append('myFile', this.state.file);
I'm trying to submit a form from Angular 7 that has text and images to a Node backend using Multer as my middleware and Express.json() as my bodyParser. The form data is there on the frontend submission and the text data is there in the backend but the image fields are empty {}. I've tried using bodyParse.json() and thre results are the same.
Here is my app.js file
const express = require('express');
// const bodyParser = require('body-parser');
const adminController = require('./controllers/admin');
const path = require('path');
const cors = require('cors')
const app = express()
const FORM_URLENCODED = 'multipart/form-data';
app.use(cors())
... my mongodb connection string ...
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', '*')
res.setHeader('Access-Control-Allow-Headers', 'Origin, Content-Type, X- Auth-Token')
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PATCH, PUT, DELETE, OPTIONS')
next();
});
// const bp = bodyParser.json()
// console.log('TCL: bp', bp);
app.use(express.json());
app.use(express.urlencoded({extended: true}));
app.use(express.static(path.join(__dirname, 'images')));
// req is not defined?!?!?!?!?
app.use(() => {
if (req.headers['content-type'] === FORM_URLENCODED) {
let body = '';
req.on('data', chunk => {
body += chunk.toString(); // convert Buffer to string
});
req.on('end', () => {
console.log(body);
res.end('ok');
});
}
})
// -- multer
const multer = require('multer');
const crypto = require("crypto");
const imgDir = 'images';
const imgStorage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, 'images')
},
filename: function(req, file, callback) {
crypto.pseudoRandomBytes(16, function(err, raw) {
if (err) return callback(err);
callback(null, raw.toString('hex') +
path.extname(file.originalname));
});
}
});
const fileFilter = ((req, file, cb) => {
// accept image only
if (!file.originalname.match(/\.(jpg|jpeg|png|gif)$/)) {
return cb(new Error('Only image files are allowed!'), false);
}
cb(null, true);
});
const upload = multer({dest: imgDir, storage: imgStorage, fileFilter:
fileFilter, limits: {fileSize: 16000} }).array('image',20);
// app.use(
// upload.fields([
// { name: 'mainImg', maxCount: 1 },
// { name: 'image', maxCount: 5 },
// ])
// );
// -- end multer
app.post('/admin/add-product', function (req, res, next) {
var path = '';
upload({dest: imgDir, storage: imgStorage, fileFilter: fileFilter,
limits: {fileSize: 16000} });
path = req.file.path;
/// path is not defined!?!?!?!?
return res.send("Upload Completed for "+path);
}, adminController.postAddProduct);
const userRoutes = require('./routes/user');
app.use('/user', userRoutes);
module.exports = multer;
module.exports.imgStorage = imgStorage;
module.exports = app;
Angular form
<form [formGroup]="prodForm" (ngSubmit)="onSubmit()" enctype="multipart/form-data">
<div class="col-md-4">
<label for="title"> <span class="required">*</span>Title: </label>
<mat-form-field>
<input class="form-control" matInput type="text" formControlName="title" #prodTitle />
<mat-error *ngIf="prodForm.get('title').invalid">Please enter a title</mat-error>
</mat-form-field>
</div>
<div class="col-md-4">
<div class="col-md-5">
<button class="btn btn-success" mat-stroked-button type="button" (click)="filePicker.click()">
Pick Image
</button>
<input type="file" #filePicker name="image" (change)="onImagePicked($event)" />
</div>
<div class="image-preview col-md-7" *ngIf="imgSrc !== '' && imgSrc">
<img [src]="imgSrc" alt="{{ prodTitle.value }}" />
</div>
</div>
<div class="col-md-12 sectButtons">
<button class="btn btn-success" (click)="onShowStep2()">Next Step</button>
<div class="clear"></div>
</div>
Angular form output
image: File {name: "some-image.jpg", lastModified: 1552012800142,
lastModifiedDate: Thu Mar 07 2019 21:40:00 GMT-0500 (Eastern Standard Time), webkitRelativePath: "", size: 42381, …}
title: "some title"
Node controller output
TCL: exports.postAddProduct -> req.body { _id: '',
title: 'some title',
image: {}, }
TCL: exports.postAddProduct -> files undefined
What am I missing? I've spent way too much time trying to figure this out.
req is not defined becuase you've not defined the req object. It is not a valid express middleware. change to
// next is optional
app.use((req, res, next) => {
if (req.headers['content-type'] === FORM_URLENCODED) {
let body = '';
req.on('data', chunk => {
body += chunk.toString(); // convert Buffer to string
});
req.on('end', () => {
console.log(body);
res.end('ok');
});
}
})