I have this problem, it turns out that I need to access the header data that is enclosed in red (Form Data), however, I can only access the information in orange (Request Headers). I need it to send information from the pdf file that is rendered on the frontend (nextjs). The library I'm using for the pdf is Kendo React, and the "proxyURL" prop is the only thing, in my opinion, that helps me send information to the backend.
Request Headers and Form Data
Target Proxy
This is the capture of the req.headers console.log, what I need is out of it, I have been seeing more than 4 hours how to access Form Data. Thanks You Very Much
Log req.headers
Attached the server code the proxy is on line 67
const express = require('express');
const { ApolloServer } = require('apollo-server-express');
const typeDefs = require('./db/schema');
const resolvers = require('./db/resolvers');
const {
GraphQLUpload,
graphqlUploadExpress, // A Koa implementation is also exported.
} = require('graphql-upload');
const jwt = require('jsonwebtoken')
const conectarDB = require('./config/db');
const { bootstrap: bootstrapGlobalAgent } = require('global-agent');
const cors = require("cors");
require('dotenv').config({path: 'variables.env'});
conectarDB();
bootstrapGlobalAgent();
// const corsOptions = {
// origin: process.env.PAGINA,
// optionsSuccessStatus: 200, // some legacy browsers (IE11, various SmartTVs) choke on 204
// credentials: true
// }
async function startServer() {
const server = new ApolloServer({
typeDefs,
resolvers,
cors: {
credentials:true,
origin: process.env.PAGINA,
optionsSuccessStatus:200
},
context: ({req}) => {
// // console.log(req.headers['authorization']);
const token = req.headers['authorization'] || '';
// console.log("headers", req.headers);
if (token) {
try {
const usuario = jwt.verify(token.replace('Bearer ', ''), process.env.SECRETA )
console.log(usuario);
return {
usuario
}
} catch (error) {
console.log("HUBO UN ERROR");
console.log(error.message);
}
}
}
});
await server.start();
const app = express();
// process.env.PAGINA
try {
app.use(graphqlUploadExpress());
app.use(express.static('public'));
// PROXY
app.all("/pdf", (req, res, ) => {
console.log("header", req.headers);
res.send('Data')
})
server.applyMiddleware({ app });
app.use(cors({
origin: process.env.PAGINA,
credentials: true,
optionsSuccessStatus:200
}))
// app.use((req, res, next) => {
// res.header("Access-Control-Allow-Origin", "*");
// res.header(
// "Access-Control-Allow-Headers",
// "Origin, X-Requested-With, Content-Type, Accept, Authorization"
// );
// if (req.method == "OPTIONS") {
// const awa = res.status(200).json({})
// const data = JSON.stringify(awa);
// console.log("data", data);
// console.log("uwuw", res.status(200).json({}));
// return res.status(200).json({});
// }
// next();
// });
// app.use(cors(corsOptions))
// await new Promise(r => app.listen({ port: process.env.PORT || 4000 }, r));
// console.log(`🚀 Server ready at http://localhost:${process.env.PORT || 4000}${server.graphqlPath}`);
// Arrancar el servidor
app.listen({ port: process.env.PORT || 4000}, () => {
console.log(`Servidor corriendo http://localhost:${process.env.PORT || 4000}${server.graphqlPath}`);
})
} catch (error) {
console.log(error);
}
// This middleware should be added before calling `applyMiddleware`.
}
startServer();
And the PDFExport component
<>
<PDFExport forceProxy={true} proxyURL={`http://localhost:4000/pdf`} proxyTarget={`Data`} ref={pdfExportComponent} paperSize="A4" fileName="archivo" key="archivo" >
<div className="body__container" ref={container}>
<header className="header__container">
<h1 className="header__title">PRESUPUESTO</h1>
<div className="header__image"></div>
</header>
<div className="section__body">
<p>Datos del paciente</p>
<h4>
Nombre: <label> {nombre}</label>
</h4>
<h4>
Apellido: <label>{apellido} </label>
</h4>
<h4>
Tipo doc: <label>{tipDoc}</label>
</h4>
<h4>
Numero doc: <label>{docNum}</label>
</h4>
<h4>
Fecha:{" "}
<label>
{dia}-{String(mes).length === 1 ? `0${mes}` : mes}-{year}
</label>
</h4>
</div>
<div className="table__container">
<Table size="sm">
<thead>
<tr>
<th className="table-cabecera-id">N°</th>
<th className="table-cabecera-categoria">CategorÃa</th>
<th className="table-cabecera-tratamiento">Tratamiento</th>
<th className="table-cabecera">Cantidad</th>
<th className="table-cabecera">C/U</th>
<th className="table-cabecera">Descuento</th>
<th className="table-cabecera">Costo</th>
</tr>
</thead>
<tbody>
{presupuesto.map((item, index) => (
<tr key={item.id}>
<td className="table-elementos">{index + 1}</td>
<td className="table-elementos" lang="es">
{item.categoria}
</td>
<td className="table-elementos" lang="es">
{item.tratamiento}
</td>
<td className="table-elementos">{item.cantidad}</td>
<td className="table-elementos">{item.precio}</td>
<td className="table-elementos">{item.descuento}</td>
<td className="table-elementos">
{item.precio * item.cantidad - item.descuento}
</td>
</tr>
))}
</tbody>
</Table>
</div>
<div className="footer">
<div className="footer__resumen">
<h4>Subtotal:</h4>
<label>S/{sumaSub}</label>
</div>
<div className="footer__resumen">
<h4>Descuento:</h4>
<label>{sumaDesc}%</label>
</div>
<div className="footer__resumen">
<h4>Total: </h4>
<label>S/{montoTotal}</label>
</div>
</div>
<div className="body__doctor">
<h4>Atentamente, Dr. {doctor.nombre} {doctor.apellido}.</h4>
</div>
<div className="footer__contacto">
<div className="footer__contacto-datos">
<h4 className="datos__title">
ODONTO<label>TRENDS</label>
</h4>
<h4>92034933838</h4>
<h4>
Direccion:{" "}
<p className="datos__direccion">
Av. Angelica Gamarra 561 Urb El Trebal - Los Olivos LIMA
</p>
</h4>
<h4>
Telefono: <p>920411227</p>
</h4>
</div>
<div className="footer__contacto-sociales">
<h4 className="footer__contacto-title">Redes sociales</h4>
<div className="sociales__container">
<h4>Odontotrends</h4>
<div className="sociales-facebook"></div>
</div>
<div className="sociales__container">
<h4>odonto_trends</h4>
<div className="sociales-instagram"></div>
</div>
<div className="sociales__container">
<h4>977 182 001</h4>
<div className="sociales-whatsapp"></div>
</div>
</div>
</div>
</div>
</PDFExport>
</>
A POST request puts the data in the request body, not as a header. Your request handler that is handling that POST request will need to read and parse the body of the request.
If this is a form post and you're using Express, then you would install the appropriate middleware - probably app.use(express.urlencoded()). Then your form values would be in req.body.
If the data is an uploaded file, then you may need additional middleware to parse the mime body such as multer.
Related
I implemented papa parse in React for the user to be able to upload the contents of a csv file into MongoDB (Atlas). Papa parse converts the Csv (with mulitple entries) into a json file which is then stored into a useState in React. Now I am trying to get this json data into MongoDB using Node/Express. It works flawlessly posting with Postman but not with React. So I guess it should be some mistake in the userFunctions.js or CSVReader.js file. Any help will be much appreciated!
// userFunctions.js
export const dataUpload = data => {
return axios.post('http://localhost:3002/event/create', {
seriennummer : data.seriennummer,
bezeichnung : data.bezeichnung,
verkaufspreis : data.verkaufspreis,
besonderheiten : data.besonderheiten,
})
.then(res => console.log('event created'))
.catch(err => console.log(err))
}
// CSVReader.js
const CSVReader = () => {
const [parsedCsvData, setParsedCsvData] = useState();
const parseFile = (file) => {
Papa.parse(file, {
header: true,
complete: (results) => {
setParsedCsvData(results.data);
},
});
};
console.log(parsedCsvData);
const onDrop = useCallback((acceptedFiles) => {
if (acceptedFiles.length) {
parseFile(acceptedFiles[0]);
}
}, []);
const {
getRootProps,
getInputProps,
isDragActive,
isDragAccept,
isDragReject,
} = useDropzone({
onDrop,
accept: "text/csv",
});
const createEvent = (e) => {
const newEvent = {
seriennummer : parsedCsvData,
bezeichnung : parsedCsvData,
verkaufspreis : parsedCsvData,
besonderheiten : parsedCsvData,
}
dataUpload(newEvent)
}
return (
<div>
<GlobalStyles />
<section
className="jumbotron breadcumb no-bg"
style={{ backgroundImage: `url(${"./img/background/subheader.jpg"})` }}
>
<div className="mainbreadcumb">
<div className="container">
<div className="row m-10-hor">
<div className="col-12">
<h1 className="text-center">CSV Datei hochladen - Uhren</h1>
</div>
</div>
</div>
</div>
</section>
<section className="container">
<div className="row">
<div className="col-lg-7 offset-lg-1 mb-5"></div>
<div
{...getRootProps({
className: `dropzone
${isDragAccept && "dropzoneAccept"}
${isDragReject && "dropzoneReject"}`,
})}
>
<input {...getInputProps()} />
{isDragActive ? (
<p>Drop the files here ...</p>
) : (
<h3>
<p>
Drag and Drop CSV File Here
</p>
</h3>
)}
</div>
<div>
<button type="submit" onClick={createEvent} class="form-control btn btnSign submit fs-3 ">CREATE NOW</button>
<div className="spacer-10"></div>
<div className="spacer-10"></div>
<table className="lead">
<thead>
<tr>
<th>Seriennummer</th>
<th>Firma</th>
<th>Preis</th>
<th>Besonderheiten</th>
</tr>
</thead>
<tbody>
{parsedCsvData &&
parsedCsvData.map((parsedData, index) => (
<tr key={index}>
<td>{parsedData.seriennummer}</td>
<td>{parsedData.bezeichnung}</td>
<td>{parsedData.verkaufspreis}</td>
<td>{parsedData.besonderheiten}</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
</section>
<Footer />
</div>
);
};
export default CSVReader;
// Controller
const createEvent = async (req, res) => {
try {
const event = await Event.insertMany(req.body)
res.json({
msg: "Created Event",
success: true,
data: event,
});
} catch (err) {
console.log(err);
res.json({
success: false,
data: err,
});
}
};
![console.log of the useState parsedCsvData][1]
[1]: https://i.stack.imgur.com/v5jZg.png
![Nodejs console][2]
[2]: https://i.stack.imgur.com/iPNXP.png
based on this error message, I believe req.body is stringified JSON. You need to do const data = JSON.parse(req.body) or use body-parser with express
Back again with another development error. This time around i'm getting a 404 error on one of the routes in my nodejs webpage. I've checked for syntax errors everywhere and apparently have none (if you guys spot something I overlooked please do tell me). The routes are registered correctly (at least as far as my understanding of routes in expressjs goes) and the link that should take me to the page (the "a" tag with a class of "btn" in the products.ejs file, line 23) that isn't loading has a correctly spelled route, because of this I am completely bamboozled as to what it could be and need your help!
I'll embed the code I currently have below so you guys can take a look, and if it's not too much to ask please explain to me what went wrong this time.
Thanks to everyone!
p.s.
My terminal isn't throwing any errors from what I could see so I couldn't attach any!
edit-product.ejs file (view):
<%- include('../includes/head.ejs') %>
<link rel="stylesheet" href="/css/forms.css">
<link rel="stylesheet" href="/css/products.css">
</head>
<body>
<%- include('../includes/navigation.ejs') %>
<main>
<form class="product-form" action="/admin/add-product" method="POST">
<div class="form-control">
<label for="title">Title</label>
<input type="text" name="title" id="title">
</div>
<div class="form-control">
<label for="imageUrl">Image Url</label>
<input type="text" name="imageUrl" id="imageUrl">
</div>
<div class="form-control">
<label for="price">Price</label>
<input type="number" name="price" id="price" step="0.01">
</div>
<div class="form-control">
<label for="description">Description</label>
<textarea name="description" id="description" rows="5"></textarea>
</div>
<button class="btn" type="submit"><% if (editing) { %>Update product<% } else { %>Add Product<% } %></button>
</form>
</main>
<%- include('../includes/end.ejs') %>
product.ejs file (view):
<%- include('../includes/head.ejs') %>
<link rel="stylesheet" href="/css/products.css">
</head>
<body>
<%- include('../includes/navigation.ejs') %>
<main>
<% if (prods.length > 0) {%>
<div class="grid">
<div class="card">
<% for (let product of prods) { %>
<article class="product-item">
<header class="card__header">
<h1 class="product__title"> <%= product.title %> </h1>
</header>
<div class="card__image">
<img src="<%= product.imageUrl %>", alt="">
</div>
<div class="card__content">
<h2 class="product__price"> $<%= product.price %> </h2>
<p class="product__description"> <%= product.description %> </p>
</div>
<div class="card__actions">
Edit
<form action="/admin/delete-product" method="POST">
<button class="btn" type="submit"> Delete </button>
</form>
</div>
</article>
<% } %>
</div>
</div>
<% } else { %>
<h1>No Products</h1>
<% } %>
</main>
<%- include('../includes/end.ejs') %>
admin.js file (routes):
const path = require('path');
const express = require('express');
const adminController = require('../controllers/admin');
const router = express.Router();
// /admin/add-product => GET
router.get('/add-product', adminController.getAddProduct);
// /admin/product => GET
router.get('/products',adminController.getProducts);
// /admin/add-product => POST
router.post('/add-product', adminController.postAddProduct);
router.get('/edit-product/:productId', adminController.getEditProduct);
module.exports = router;
product.js file:
const fs = require('fs');
const path = require('path');
const p = path.join(
path.dirname(process.mainModule.filename),
'data',
'products.json'
);
const getProductsFromFile = cb =>{
fs.readFile(p, (err, fileContent) => {
if(err) {
cb([]);
} else{
cb(JSON.parse(fileContent));
}
});
};
module.exports = class Product {
constructor(title, imageUrl, description, price) {
this.title = title;
this.imageUrl = imageUrl;
this.description = description;
this.price = price;
}
save() {
this.id = Math.random().toString();
getProductsFromFile(products => {
products.push(this);
fs.writeFile(p, JSON.stringify(products), (err) => {
console.log(err);
});
});
}
static fetchAll(cb) {
getProductsFromFile(cb);
};
static findById(id, cb) {
getProductsFromFile(products => {
const product = products.find(p => p.id === id);
cb(product);
});
};
};
admin.js file (controller):
const Product = require('../models/product');
exports.getAddProduct = (req, res, next) => {
res.render('admin/edit-product', {
pageTitle: 'Add Product',
path: '/admin/add-product',
editing: false
});
};
exports.postAddProduct = (req, res, next) => {
const title = req.body.title;
const imageUrl = req.body.imageUrl;
const price = req.body.price;
const description = req.body.description;
const product = new Product(title, imageUrl, description, price);
product.save();
res.redirect('/');
};
exports.getEditProduct = (req, res, next) => {
const editMode = req.query.edit;
if (!editMode) {
return res.redirect('/');
}
const prodId = req.params.productId;
Product.findById(prodId, product => {
if(!product) {
return res.redirect('/');
}
res.render('admin/edit-product', {
pageTitle: 'Edit Product',
path: '/admin/edit-product',
editing: editMode,
product: product
});
});
};
exports.getProducts = (req, res, next) => {
Product.fetchAll(products => {
res.render('admin/products', {
prods: products,
pageTitle: 'Admin Products',
path: 'admin/products'
});
});
};
Upon looking yet again at the videos I found the answer to my problem. Everything in the code is written correctly, the problem relies on the url I was using. The problematic route was "/admin/edit-product" because there isn't a route connecting to that view, instead the route in the code is "/edit-product/:productId". My mistake was that I had to specify manually the url in my browser because I haven't coded it otherwise.
So I am working on payment processing with stripe. When I go to the payments on stripe it says they are uncompleted, the customer did not define the payment method...
React component
useEffect(() => {
const getClientSecret = async () => {
const responce = await axios({
method: "post",
url: `/payments/create?total=${getBasketTotal(basket) * 100}`,
});
setClientSecret(responce.data.clientSecret);
};
getClientSecret();
}, [basket]);
console.log("THE SECRET IS >>> ", clientSecret);
const submitHandler = async (e) => {
//stripe magic
e.preventDefault();
setProcessing(true);
const payload = await stripe
.confirmCardPayment(clientSecret, {
payment_method: {
card: elements?.getElement(CardElement),
},
})
.then(({ paymentIntent }) => {
//paymentIntent = payment confirmation
console.log(paymentIntent);
setSucceeded(true);
setError(null);
setProcessing(false);
dispatch({
type: "EMPTY_BASKET",
});
history.replace("/orders");
});
};
const changeHandler = (e) => {
//stripe magic
setDisabled(e.empty);
setError(e.error ? e.error.message : "");
};
return (
<div className="payment">
<div className="payment__container">
<h1>
Checkout(<Link to="/checkout">{basket?.length} items</Link>)
</h1>
<div className="payment__section">
<div className="payment__title">
<h3>Delivery Address</h3>
</div>
<div className="payment__address">
<p>{user?.email}</p>
<p>123 React Lane</p>
<p>Los Angeles, CA</p>
</div>
</div>
<div className="payment__section">
<div className="payment__title">
<h3>Review items and delivery</h3>
</div>
<div className="payment__items">
<FlipMove>
{basket.map((item) => (
<div>
<CheckoutProduct
id={item.id}
title={item.title}
image={item.image}
price={item.price}
rating={item.rating}
/>
</div>
))}
</FlipMove>
</div>
</div>
<div className="payment__section">
<div className="payment__title">
<h3>Payment Method</h3>
</div>
<div className="payment__details">
<form onSubmit={submitHandler}>
<CardElement onChange={changeHandler} />
<div className="payment__priceContainer">
<CurrencyFormat
renderText={(value) => (
<>
<h3>Order Total: {value}</h3>
</>
)}
decimalScale={2}
value={getBasketTotal(basket)}
displayType={"text"}
thousandSeperator={true}
prefix={"$"}
/>
<button
disabled={
processing || disabled || succeeded || clientSecret === null
}
>
<span>{processing ? <p>Processing</p> : "Buy Now"}</span>
</button>
</div>
{error && <div>{error}</div>}
</form>
</div>
</div>
</div>
</div>
);
}
export default Payment;
Node JS
const app = express();
// - Middlewares
app.use(cors({ origin: true }));
app.use(express.json());
// - API routes
app.get("/", (request, responce) => responce.status(200).send("hello world"));
app.post("/payments/create", async (request, responce) => {
const total = request.query.total;
console.log("Payment Request Received >>> ", total);
const paymentIntent = await stripe.paymentIntents.create({
amount: total,
currency: "usd",
});
// OK - Created
responce.status(201).send({
clientSecret: paymentIntent.client_secret,
});
});
// - Listen command
exports.api = functions.https.onRequest(app);
I have two questions: 1st, is this going to b a problem when working on order history? an 2nd, how do I fix this?
Thank you in advance
This is the route code:
router.get('/compose/:ID', function(req, res, next) {
var random = Math.floor((Math.random() * 1000000) + 1);
console.log("random = " + random);
res.render('compose', { random: random, Id:req.params.ID });
})
.post(function(req, res, next) {
var to = '917985754084';
var from = 'GrumpyText';
var text = req.body.OTP;
console.log(text);
nexmo.message.sendSms(from, to, text, function(err,success){
if(success)
console.log("SMS sent successfully!");
else {
console.log("error");
}
});
});
This is the handlebar code:
<main role="main" class="container">
<div class="jumbotron">
<h1>List of Contacts</h1>
<table class="table table-striped">
<thead>
<tr>
<th scope="col"></th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<form method="post" enctype="multipart/form-data">
<tr>
<td><input type="text" name="OTP" class="form-control" value="Hi. Your OTP is : {{random}}"></td>
<td></td>
</tr>
<tr>
<td><button type="submit" class="btn btn-lg btn-primary btn-block">Submit</button>
</td>
</tr>
</form>
</tbody>
</table>
</div>
</main>
Its coming to the route but the console is not printing the 'text'. aka console.log(text) means req.body.OTP is not printing anything. Earlier it was printing undefined.
Could you please rectify where it is stucking perhaps?
The issue you are hitting is body-parser doesn't handle multipart/form-data.
There are several options, but one of those is multer.
\* add these for multi-part*\
var multer = require('multer')
var upload = multer();
\* other code *\
router
.get('/compose/:ID', function (req, res, next) {
var random = Math.floor(Math.random() * 1000000 + 1);
console.log('random = ' + random);
res.render('compose', { random: random, Id: req.params.ID });
})
.post('/compose/:ID', upload.none(), function (req, res, next) {
var to = '917985754084';
var from = 'GrumpyText';
var text = req.body.OTP;
nexmo.message.sendSms(from, to, text, function (err, success) {
if (success) console.log('SMS sent successfully!');
else {
console.log('error');
}
});
});
I want to create a module, which keeps an open connection to Flickr API and keeps on receiving new recent photos.
I've tried the 'agentkeepalive' node module, but cloudfront seems to block the requests. This is what my current module code looks like, obviously, the fetch now only runs once:
Server side
require('dotenv').config()
var Flickr = require('flickr-sdk')
var flickr = new Flickr(process.env.FLICKR_API_KEY)
var express = require('express')
var app = express()
app.use(function(req, res, next) {
res.header('Access-Control-Allow-Origin', 'http://localhost:3000')
res.header(
'Access-Control-Allow-Headers',
'Origin, X-Requested-With, Content-Type, Accept',
)
next()
})
app.get('/fetch', function(req, res) {
(() =>
flickr.photos
.getRecent()
.then(result => {
return res.send(result.body.photos.photo)
})
.catch(err => {
console.error('Error: ', err)
}))()
})
const PORT = process.env.PORT || 5000
app.listen(PORT, () => console.log(`Server started on port ${PORT}`))
Client side
import './App.css'
import 'bootstrap/dist/css/bootstrap.css'
import React, { Component } from 'react'
import axios from 'axios'
export class App extends Component {
constructor(props) {
super(props)
this.state = {
fetchClicked: false,
photos: [],
}
}
onFetchClick = () => {
this.state.fetchClicked
? this.setState({ fetchClicked: false })
: this.setState({ fetchClicked: true }, () => {
axios.get('http://localhost:5000/fetch').then(response => {
this.setState({
photos: response.data,
})
})
})
}
render() {
const { fetchClicked } = this.state
return (
<div className="App p-5 bg-secondary">
<h1>Flickr Streamer </h1>
{fetchClicked ? (
<button className="btn btn-info" disabled>
Streaming...
</button>
) : (
<button className="btn btn-info " onClick={() => this.onFetchClick()}>
Start the stream!
</button>
)}
<div>{this.state.dataReceived}</div>
<table className="table table-dark mt-5">
<thead>
<tr>
<th scope="col">Photo</th>
<th scope="col">Title</th>
</tr>
</thead>
<tbody>
{this.state.photos.map(item => {
return (
<tr key={item.id}>
<td>
<img
src={`https://farm${item.farm}.staticflickr.com/${item.server}/${item.id}_${item.secret}.jpg`}
/>
</td>
<td scope="row" className="w-50">
{item.title || 'No name'}
</td>
</tr>
)
})}
</tbody>
</table>
</div>
)
}
}
export default App
Polling is usually the way to do this kind of thing. This is how I would do it:
fetch = () => axios.get('http://localhost:5000/fetch')
.then(({data}) => this.setState({ photos:data })
onFetchClick = () =>
this.setState({ fetchClicked: !this.state.fetchClicked }),
() => this.fetch()
.then(() => setInterval(() => this.fetch(), 15 * 1000))
This doesn't deal with the user clicking the button more than once, but if that callback only executes if the state changed, or you disable the button when it is clicked, that would be handled for you by that. Otherwise, you'd have to handle it.