React JS Fetch request fails with 'Cannot POST' - node.js

Im trying to implement a simple fetch request to the server as follows
<input type="text" id="usersearchfield" onKeyUp={(e)=>sendData(e.target.value)}/>
function sendData (input){
fetch('/api/user/userSearch',{
method:'POST',
headers:{'Accept': 'application/json',
'Content-Type': 'multipart/form-data'},
body: JSON.stringify({username: input})
})
.then(res =>res.json)
.then(data =>{
let input = data.input
console.log("input is:",input)
})
}
This is my server's side index.js
app.use(express.json());
app.use(express.urlencoded({ extended: true}));
app.use("/api/user" , userRouter);
routes
//serach user
router.post('/userSearch',userController.userSearch)
controller
const userSearch = async (req, res) => {
const input =req.body.username
console.log("SERVER GOT",input)
let search = await User.find({username: {$regex: new RegExp('^'+input+'.*','i')}}).exec()
search = search.slice(0,10)
res.send({input:search})
console.log("INPUT IS ",input)
}
When i try to execute this code i get POST http://localhost:3000/api/user/userSearch 404 (Not Found)
what im missing?

Related

Save JSON file to local folder on client with Nextjs/ NodeJs and Firebase hosting/functions

I'm using NextJS for my application and i would like to write an JSON-file to the client in a function. On my localhost everything works fine and without any problem, but the application gets build and deployed to firebase it isn't working anymore.
I already tried multiple things, i already created the function in the api folder of NextJs and also created an localhost node server and call them in nextjs API as:
var fs = require('fs').promises;
export default function (req, res) {
console.log(JSON.stringify(req.body))
let Data= JSON.stringify(req.body)
fetch('http://localhost:9091/data', {
method: 'POST',
headers: {
'Accept': 'application/json, text/plain, */*',
'Content-Type': 'application/json'
},
body: Data
})
.then((response) => {
console.log('here')
return response.json(); // or .text() or .blob() ...
})
.then((text) => {
console.log(text)
res.status(200)
// text is the response body
})
.catch((e) => {
// error in e.message
});
As said this works when the application runs on localhost but not on firebase hosting/functions.
The node server looks like:
var express = require('express');
var app = express();
const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(express.urlencoded({ extended: false }));
app.use(express.json());
var fs = require('fs').promises;
app.get('/', function (req, res) {
res.send('Hello World');
})
app.post('/data', function (req, res) {
res.send('Hello World');
let Order = req.body;
console.log(Order)
fs.readFile("object.json",'utf8').then(data =>{
let json = JSON.parse(data);
json.push(Order);
fs.writeFile("object.json", JSON.stringify(json)).then( () => { console.log('Append Success'); })
.catch(err => { console.log("Append Failed: " + err);});
})
})
var server = app.listen(9091, function () {
var host = server.address().address
var port = server.address().port
console.log("Example app listening at http://%s:%s", host, port)
})
What I'm trying to achieve is that data is appended to the JSON file and stored locally on the client.
Does anyone have an idea how to handle this properly?

Why I get this POST http://localhost:3000/ 404 (Not Found) when posting front to back?

I was trying to post data from frontend to backend server. But I have these 2 error found:
POST http://localhost:3000/ 404 (Not Found)
error Unexpected token '<', "<!DOCTYPE "... is not valid JSON
And literally have no idea... please help me!!!
Here is my folder structure:
The sendmail is the backend part, its folder is inside the react frontend.
And the frontend code for posting data is:
const [subscribeEmail, setSubscribeEmail] = useState()
console.log(subscribeEmail)
const handleOk = async () => {
await fetch('http://localhost:3001/', {
method: 'post',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
email: subscribeEmail
})
})
.then(response => response.json())
.then(data => JSON.parse(data))
.catch(err => console.log('error', err.message))
setModal(false)
}
return (
<h3 onClick={() => setModal(true)}>Sign up for our daily insider! Click me to do so! </h3>
<Modal
title="Thanks for subscribe our daily insider!"
style={{
top: 20,
}}
open={modal}
centered
onOk={handleOk}
onCancel={() => setModal(false)}
>
<p>Tell us your email here:</p>
<Input onChange={(e) => { setSubscribeEmail(e.target.value) }} />
</Modal>
)
Then is the code of backend:
const express = require('express')
const bodyParser = require('body-parser')
// const https = require('https')
const cors = require('cors')
const sgMail = require('#sendgrid/mail')
sgMail.setApiKey('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')
const app = express()
app.use(
bodyParser.urlencoded({
extended: true
})
)
app.use(cors)
app.use(express.static('public'))
app.use(bodyParser.json())
app.post('/', (req, res) => {
const email = req.body.email
console.log(email)
})
app.listen(3001, function (err) {
if (err) console.log('listen error', err)
console.log('successfully connected')
})
The error is catched in the frontend code.
Please help me! So grateful!

html file does not appear after logging without any error

I am new to server-side programming.
I am trying to serve a HTML file (mapview.html) after authentication ,but it does not appear without any error.
there is no problem with authentication process. I expect when I click on login button, the codes check req data
and after validating, mapview.html pop up but nothing happen.
res.sendFile() causes in jquery part, console.log(res), get me all html codes in console line of chrome.
files directory:
src
index.js
db
public
index.html
mapview.html
middleware
auth.js
routers
user
task
model
user
task
index.html
$('div[name="logIn"]').click( () => { // select a div element that its name is logIn
console.log('LOG-IN:')
$.ajax({
url: '/login',
data: $('#loginForm').serialize(), // Get email and pass from login form
type: 'POST',
success: function (res) {
console.log(res)
}
})
})
user.js
router.post('/login', async (req, res) => {
try {
const user = await User.findByCredentials(req.body.email, req.body.password)
const token = await user.generateAuthToken()
const publicDir = path.join(__dirname, '../public')
res.sendFile(path.join(publicDir + '/mapview.html'));
} catch (e) {
res.status(400).send(e)
}
})
index.js
const express = require('express');
require('./db/mongoose');
const bodyParser = require('body-parser');
const userRouter = require('./routers/user');
const taskRouter = require('./routers/task');
const app = express();
const port = process.env.PORT || 3000;
app.use(express.json()); // Parse recieved json body data from Postman
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
app.use(express.static(__dirname + '/public'));
app.use(userRouter);
app.use(taskRouter);
app.listen(port, () => {
console.log('server is run on port:' + port)
});
when you are making the HTTP post request from index.html using ajax to verify user authentication details, on successful authentication you are sending a static html file which is simply a text response and will not be rendered as a web page (as you were expecting).
To solve this problem,
Create a separate route for accessing the mapview.html
app.get('/map', (req, res) => {
res.sendFile(__dirname + '/public' + '/mapview.html');
});
In your ajax response just redirect to the map route
$.ajax({
url: '/login',
data: $('#loginForm').serialize(), // Get email and pass from login form
type: 'POST',
success: function (res) {
console.log(res);
window.location.href = '/map'; // redirect to map route
}
});
I updated the codes and it looks like following code .
As I mention in the past comment , I need to authenticate before refirect through .href = '/map' and I do not know how to attach token to .href='/map.
we usually send token as header with ajax like this:
headers:{"Authorization": localStorage.getItem('token')}
in case I add it to .href ,something like this window.location.href = '/map + "?token=MY_TOKEN" , how can i get it in auth method?
user.js
router.post('/login', async (req, res) => {
try {
const user = await User.findByCredentials(req.body.email,
req.body.password)
const token = await user.generateAuthToken()
res.send({user, token})
} catch (e) {
res.send(e)
res.status(400).send(e)
}
})
router.get('/map', auth, (req, res) => {
const publicDir = path.join(__dirname, '../public')
res.sendFile(path.join(publicDir + '/mapview.html'));
});
index.html
$('div[name="logIn"]').click( () => {
$.ajax({
url: '/login',
data: $('#loginForm').serialize(),
type: 'POST',
success: function (res) {
localStorage.setItem('token', res.token);
window.location.href = '/map';
}
})
})

Express JS is receiving an empty req.body from ReactJS

I am currently having a problem with React and Express JS form submit function. It seems like my nodeJS running on port 5000 is receiving an empty object from my ReactJS running on port 8080 using fetch method.
React : Contact.js
handleSubmit(e)
{
e.preventDefault();
var data = {
name: this.state.name,
contact: this.state.contact,
email: this.state.email,
message: this.state.message,
}
var url = 'http://localhost:5000/api/insertUsers';
fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
mode: 'no-cors',
body: JSON.stringify(data),
})
.catch((error) => {
console.log(error);
});
}
NodeJS : server.js
const express = require('express');
const { Client } = require('pg');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.post('/api/insertUsers', function(req, res) {
res.setHeader('Content-Type', 'text/plain')
res.write('you posted:\n')
res.end(JSON.stringify(req.body, null, 2))
});
app.listen(5000, () => {
console.log('listening on port 5000');
});
Change the order of bodyparser middleware like this.
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
You are sending a request with the content-type of 'application/json' but express is expecting a content-type of 'text/json'. Usually, when req.body is empty content-type is the first suspect you should be looking at.
I am ashamed that I struggled with this for hours. I still haven't gotten it to work with file uploads.
But I did get it to work with a normal form by encoding JSON and sending that along with axios, instead of fetch
My js code
var data = {
id: this.state.id,
}
console.log('data',data)
var bodyFormData = new FormData();
bodyFormData.set('id', this.state.id);
var url = ' http://localhost:3000/get-image-by-id';
console.log("bodyFormData: ", bodyFormData);
axios({
method: 'post',
url: url,
data: data,
// headers: {'Content-Type': 'multipart/form-data' }
headers: {'Content-Type': 'application/x-www-form-urlencoded' }
})
.then(function (response) {
//handle success
console.log(response);
})
.catch(function (response) {
//handle error
console.log(response);
});
Form Code
<form method="POST" onSubmit={this.handleSubmit} >
<label>
Transaction ID
<input
type="text"
name="id"
value={this.state.id}
onChange={this.handleInputChange}
/>
</label>
<button type="submit">Submit</button>
</form>
```
EDIT
fetch(url, {
method: 'POST',
body: JSON.stringify(data),
mode: 'no-cors'
}).then((result)=>{
console.log("output" + result.json());
})
.catch((error) => {
console.log(error);
});
EDIT 2
for backend, install cors and add the following lines before route.
var cors = require('cors')
app.use(cors())
EDIT 3
perform npm install morgan then copy these lines inside the code
var morgan = require('morgan');
app.use(morgan('dev'));
I didn't look at your code close enough. My bad
app.post('/api/insertUsers', function(req, res) {
res.setHeader('Content-Type', 'text/plain')
res.write('you posted:\n')
res.end(JSON.stringify(req.body, null, 2))
});
Should be
app.post('/api/insertUsers', function(req, res) {
res.json(req.body)
});
try using axios instead of fetch
I rewrote ur code like this and it works perfectly
server
const express = require('express');
const { Client } = require('pg');
const bodyParser = require('body-parser');
const app = express();
const cors = require("cors");
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.post('/api/insertUsers', function(req, res) {
// console.log(req);
console.log(req.body);
res.send(req.body);
});
app.listen(3001, () => {
console.log('listening on port 3001');
});
react (ensure you have axios installed)
handleSubmit(e){
e.preventDefault();
var data = {
name: "zadiki",
contact: "0702002109",
email: "zadiki",
message: "test",
}
console.log("wow");
var url = ' http://localhost:3001/api/insertUsers';
axios.post(url,data)
.then(response=>console.log(response))
.catch(e=>console.log(e))
}
Hello I ended up getting mine working after I ran into the same problem.
I noticed your react code has "mode: 'no-cors'," that was causing problems with mine so I removed it.
-------- Below is my handle submit code for React ------------
const handleSubmit = (event) => {
event.preventDefault();
const url = "http://localhost:3001/register"
const options = {
method: "POST",
body: JSON.stringify(formData),
headers: {
"Content-Type": "application/json"
}
}
fetch(url, options)
.then(res => res.json())
.then(res => console.log(res))
}
I used express.json instead of bodyParser. You also had a typo in your express code, it should say res.send instead of res.end
--------- Below is my Node Express Code -----------
const express = require('express');
const app = express();
const cors = require('cors');
const multer = require('multer');
// Middlewares
app.use(cors({ origin: 'http://localhost:3000', }))
app.use(express.json())
app.use(express.urlencoded({ extended: true }))
app.use(multer().array());
app.post('/register',(req, res) => {
console.log(req.body)
res.status(200)
.json({status:"Success", data:{body: req.body })
});
app.listen(3001, () => console.log(`Running on 3001`))
I was able to send form data using postman and react using the code above. Feel free to change it to accommodate your needs.

NextJS and React: Cannot read property 'email' of undefined

I try to send data from my client to my server. For that, i use React with NextJS, because you have the server and client-side in one app.
I use the following handleSubmitFunction:
handleSubmit() {
const email = this.state.email;
fetch('/', {
method: 'POST',
body: email,
});
}
and this is my server.js file in the located in / at my project
const express = require('express')
const next = require('next')
const bodyParser = require('body-parser')
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
app.prepare()
.then(() => {
const server = express()
//parse application
server.use(bodyParser.urlencoded({ extended: false}))
//parse application/json
server.use(bodyParser.json())
server.post('/', (req, res) => {
console.log(req.body.email);
res.end("success!");
})
server.get('*', (req, res) => {
return handle(req, res)
})
server.listen(3000, (err) => {
if (err) throw err
console.log('> Ready on http://localhost:3000')
})
})
.catch((ex) => {
console.error(ex.stack)
process.exit(1)
})
When the handleSubmit Function is running, i get the following Output from the Server Console:
Cannot read property 'email' of undefined
Where exactly is my mistake?
I have little experience in node JS environments. I would be very grateful if you could show me concrete solutions. Thank you for your replies.
It seems you have to parse header and JSON.stringify the email.
fetch('/', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({email:email}),
}).then((res)=> console.log('Worked'))

Resources