Send data from JavaScript to node.js - javascript

Below is the JavaScript code. How can I send the players array to node.js?
let players = [];
for(var i=0; i<22; i++){
players.push($(".card > button").eq(i).attr("value"));
}
Below is the node.js code.
const express = require("express");
const bodyParser = require("body-parser");
const mySql = require("mySql");
const app = express();
app.use(express.static("public"));
app.use(bodyParser.urlencoded({extended: true}));
app.set('view engine', 'ejs');
app.get("/play", function(req, res){
res.render("PlayGame");
});
app.post("/play", function(req, res){
res.render("PlayGame");
});
I need to catch the players array at /play route in node.js. How can I do that?

Yes, you can send data from the browser Javascript to your node.js app. You would use an Ajax call and use either the XMLHttpRequest API or the more modern fetch() API to send the data. You would create a route in your nodejs server such as /play and then send the data with the request. Your server will then need to parse the incoming data (depending upon how it was sent) and can then act on it.
You will also have to decide if you're sending a GET, POST or PUT request (picking what is appropriate based on typical REST design and architecture). If this is starting a game and you're sending a bunch of data with it, then you would probably use a POST request and send the data as JSON in the body of the request.
In Express, here's how you'd receive that type of data:
app.use(express.json());
app.post("/play", (req, res) => {
console.log(req.body); // this would be the data sent with the request
res.send("game started");
});
In the browser, here's how you could send an array of players to your server.
fetch("/play", {
method: "POST",
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(players)
}).then(response => {
// this line of code depends upon what type of response you're expecting
return response.text();
}).then(result => {
console.log(result);
}).catch(err => {
console.log(err);
});
See the "Using Fetch" page on MDN for more info.

On the client side you would need something like this:
const postData = data => {
const body = JSON.stringify(data);
return fetch('https://your.url/play', {
method: 'POST', // GET, POST, PUT, DELETE, etc.
mode: 'cors', // no-cors, cors, same-origin
cache: 'no-cache', // default, no-cache, reload, force-cache, only-if-cached
credentials: 'same-origin', // include, same-origin, omit
headers: {
'Content-Type': 'application/json',
},
redirect: 'follow', // manual, follow, error
referrer: 'no-referrer', // no-referrer, client
body
})
.then(response => response.json()) // parses JSON response into native JavaScript objects
}
const players = ['a', 'b', 'c'];
postData({data: players})
.then(json => {
console.log(json);
})
.catch(e => console.log(e));
On the server side you would need something like this:
app.use(express.json());
app.post("/play", (req, res) => {
const players = req.body.data;
...
...
});

Related

How to send data from React to Node?

I am really new to node and wanted to know how to send some data from my frontend using react to my backend (Node JS).I want to send some string to my backend,is this the process or is it a completely different thing?
useEffect(() => {
fetch("/api")
.then((res) => res.json())
.then((data) => setData(data.message));
}, []);
index.js file
// server/index.js
const express = require("express");
const PORT = process.env.PORT || 3001;
const app = express();
app.get("/api", (req, res) => {
const tmp=req.body;
res.json({ message: tmp });
});
app.listen(PORT, () => {
console.log(`Server listening on ${PORT}`);
});
Your /api route is listening to GET requests. GET requests can't contain body, therefore you won't be receiving anything inside the body.
If you want to pass data with get request, you can either use query parameters or URL parameters. Passing query params would be something like,
fetch('/api?' + new URLSearchParams({
message: 'message',
}))
To receive this from backend and use it as a response, you can access the query parameters like below using req.query,
app.get('/api', function(req, res) {
res.json({
message: req.query.message
});
});
You can also send data using URL parameters with GET request, instead of using query parameters.
I suggest taking a deeper look at HTTP requests.
you need to use post method, here is the client side using fetch api(from mdn docs):
// Example POST method implementation:
async function postData(url = '', data = {}) {
// Default options are marked with *
const response = await fetch(url, {
method: 'POST', // *GET, POST, PUT, DELETE, etc.
mode: 'cors', // no-cors, *cors, same-origin
cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
credentials: 'same-origin', // include, *same-origin, omit
headers: {
'Content-Type': 'application/json'
// 'Content-Type': 'application/x-www-form-urlencoded',
},
redirect: 'follow', // manual, *follow, error
referrerPolicy: 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
body: JSON.stringify(data) // body data type must match "Content-Type" header
});
return response.json(); // parses JSON response into native JavaScript objects
}
postData('https://example.com/answer', { answer: 42 })
.then(data => {
console.log(data); // JSON data parsed by `data.json()` call
});
and for backend, you can handle it this way (from express docs):
const express = require("express");
const bodyParser = require("body-parser");
const router = express.Router();
const app = express();
//Here we are configuring express to use body-parser as middle-ware.
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
router.post(‘/handle’,(request,response) => {
//code to perform particular action.
//To access POST variable use req.body()methods.
const {answer} = request.body;
res.json({answer});
});
// add router in the Express app.
app.use("/", router);

SyntaxError: Unexpected token " in JSON at position 0

I have an error with request to express. I have this fetch:
fetch(`http://localhost:4200/dist/js/server.min.js`, {
method: "POST",
// mode: 'no-cors',
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(`<html><body><div style="background-color: yellow;"><p>Hello World!</p></div></body></html>`),
}).then((response) => {
console.log(response)
})
And I have such a code for my express server:
const { exec } = require("child_process"),
express = require("express"),
bodyParser = require('body-parser'),
webshot = require('webshot'),
PORT = 4200,
app = express(),
cors = require('cors')
// app.use(cors())
app.use((req, res, next) => {
res.append('Access-Control-Allow-Origin', 'http://localhost:4242');
res.append('Access-Control-Allow-Methods', 'POST', 'GET', 'OPTIONS');
res.append('Access-Control-Allow-Headers', 'Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With');
res.append('Access-Control-Allow-Credentials', 'true');
next();
});
// app.use(express.json());
app.use(bodyParser.json());
app.get('/dist/js/server.min.js', (req, res) => {
res.send('<h1>Hello</h1>')
})
app.post('/', function(req, res) {
htmlData = req.body
screen(htmlData) // just my function
});
app.listen(PORT, () => {
console.log(`What's my age again? ${PORT}, I guess.`)
});
And I've got this error in browser:
POST http://localhost:4200/dist/js/server.min.js 400 (Bad Request)
And this in console:
SyntaxError: Unexpected token " in JSON at position 0
at JSON.parse (<anonymous>)
at createStrictSyntaxError (/home/joe/Documents/vscode-projects/html-projects/swipeskins/node_modules/body-parser/lib/types/json.js:158:10)
at parse (/home/joe/Documents/vscode-projects/html-projects/swipeskins/node_modules/body-parser/lib/types/json.js:83:15)
at /home/joe/Documents/vscode-projects/html-projects/swipeskins/node_modules/body-parser/lib/read.js:121:18
at invokeCallback (/home/joe/Documents/vscode-projects/html-projects/swipeskins/node_modules/body-parser/node_modules/raw-body/index.js:224:16)
at done (/home/joe/Documents/vscode-projects/html-projects/swipeskins/node_modules/body-parser/node_modules/raw-body/index.js:213:7)
at IncomingMessage.onEnd (/home/joe/Documents/vscode-projects/html-projects/swipeskins/node_modules/body-parser/node_modules/raw-body/index.js:273:7)
at IncomingMessage.emit (events.js:198:15)
at endReadableNT (_stream_readable.js:1139:12)
at processTicksAndRejections (internal/process/task_queues.js:81:17)
I guess, server has problems with parsing json data. But why? What is wrong with code?
Thanks a lot for your time, I would be very grateful to hear something from you if you have some thoughts about my situation.
Your JSON's top level data type is a string:
JSON.stringify(`<html>...</html>`);
The current version of the JSON specification allows the top level data type in the JSON text to be any JSON data type.
The original version only allowed an object or an array.
The error message says that having " as the first character is an error, which implies that it doesn't support strings as the top level data type (and thus implements the original specification).
Either change the structure of the JSON so it starts with an object or an array:
{
"html": "<html>...</html>"
}
or change the data format you are sending:
"Content-Type: text/html"
and
body: "<html>...</html>" // without JSON.stringify
Obviously, you'll need to change the server-side code to accept the changed format.
The problem is that the express JSON body parser by default only accepts inputs that can be parsed as JSON objects. However, you can change it to accept other types of valid JSON data (including strings, like in the OP) by disabling "strict" parsing:
app.use(express.json({strict: false}));
This is the workaround the worked for me.
Reference: https://github.com/expressjs/express/issues/1725#issuecomment-22844485
On request body you are not parsing a DOM element, so you can do the following:
const parser = new DOMParser();
const raw = '<html><body><div style="background-color: yellow;"><p>Hello World!</p></div></body></html>';
const body = parser.parseFromString(raw, 'text/html');
fetch(`http://localhost:4200/dist/js/server.min.js`, {
method: "POST",
// mode: 'no-cors', // If you use 'no-cors' you will not get response body and some headers
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(body),
}).then((response) => {
console.log(response);
})

The req.body is empty in node.js sent from react

I create an app in react. I am trying to use fetch with a post to a different port of localhost. I received the req on the server, but my body is empty. Why my body is empty? I don't understand.
Code in React function:
export default function Sending() {
async function handleSubmit(e) {
e.preventDefault()
try{
let result = await fetch('http://localhost:5000',{
method: 'post',
mode: 'no-cors',
headers: {
'Accept': 'application/json',
'Content-type': 'application/json',
},
body: JSON.stringify({ email: 'example#gmail.com' })
})
console.log(result)
} catch (error){
console.log(error)
}
}
return (
<>
Have a Form here
</>
)
}
the console log of browser:
Response {type: "opaque", url: "", redirected: false, status: 0, ok: false, …}
body: null
bodyUsed: false
headers:
Headers {}
ok: false
redirected: false
status: 0
statusText: ""
type: "opaque"
url: ""
__proto__: Response
my simple server hold on node.js:
const express = require('express')
const bodyParser = require('body-parser')
const app = express()
const port = process.env.PORT || 5000
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.post('/', (req, res) => {
console.log(req.body)
res.send("Hello")
})
app.get('/hello', (req, res) => {
res.send("Hello, Benny")
})
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})
You are trying to post JSON
To do that you need to set a 'Content-type': 'application/json' request header
This is only allowed on a cross-origin request when you have permission from CORS (from a preflight request).
You said mode: 'no-cors', a declaration that you do not have or want permission to do anything from CORS, so the browser will silently ignore anything that needs CORS permission
The request arrives at the server without 'Content-type': 'application/json' so the body-parser doesn't know that it needs to decode the JSON
You need to:
Remove mode: 'no-cors'
Configure the server to support CORS including for preflight requests
This is most easily done with the cors module
const cors = require('cors')
const app = express()
const corsOptions = {
origin: 'http://example.com',
}
const configuredCors = cors(corsOptions);
app.options('*', configuredCors)
app.post('/', configuredCors, (req, res) => {
console.log(req.body)
res.send("Hello")
})
Consider installing cors and add it to your code such as shown bellow
const cors = require('cors')
app.use(cors())
Then with the help of morgan
const morgan = require('morgan');
Consider reading a previous similar case as shown here
Express JS is receiving an empty req.body from ReactJS
From the first glacne; you are sending over a string with the stringify. Node body-parser trys to parse the json. Try removing the stringify and just sending the object over.

JSON is becoming empty upon hitting server code

I am sending a fetch request with a JSON payload from my webpage like this:
let raw = JSON.stringify({"name":"James","favourite":"books"})
var requestOptions = {
method: 'POST',
body: raw
};
let send = () => {
fetch("http://mywebsite.herokuapp.com/send", requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
}
On the server side I am getting an empty body {}. Here is the code I use to monitor that:
app.post('/send', (req, res) => {
console.log(req.body)
})
When I send the exact same code generated with Postman to server — somehow everything works fine, and I get the correct JSON. Please help me understand why that is.
On the server, req.body will be empty until you have middleware that matches the content type in the POST and can then read the body from the response stream and populate req.body with the results.
// middleware to read and parse JSON bodies
app.use(express.json());
app.post('/send', (req, res) => {
console.log(req.body);
res.send("ok");
});
And, then on the client side, you have to set the matching content-type, so the server-side middleware can match the content-type and read and parse it:
const requestOptions = {
method: 'POST',
body: raw,
headers: {
'Content-Type': 'application/json'
},
};

client (fetch) and server (nodejs http) don't understand each other?

I try to wrap my mind around nodejs at the moment.
So I've created a client:
let myHeaders = {
'Content-Type': 'application/json',
'Accept': 'application/json'
};
let myBody = {
aString: "Test"
};
fetch("http://localhost:8099/", {
method: 'post',
mode: 'no-cors',
headers: myHeaders,
body: JSON.stringify(myBody)
})
.then(result => {
return result.text();
})
.then(text => {
// do stuff with text from server
});
And I have created a server:
// request needed modules
const http = require('http');
// init server
let server = http.createServer(logic);
server.listen(8099);
// server logic
function logic (req, res) {
var body = req.body;
res.end("Hello");
}
Two problems:
1) The sever does not get the body (req.body is undefined).
UPDATE
See my answer below.
--
2) The client does not receive "Hello" (result.text() returns "").
UPDATE
2 is solved by:
Changing this on the client
fetch("http://localhost:8099/", {
method: 'post',
mode: 'no-cors', <-- CHANGE to: mode: 'cors'
...
Adding this on server
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
--
I don't get what I do wrong here...
Your Node.js code has nothing which would generate the HTML document containing the JS that calls fetch.
This means you must be making a cross-origin request (this is supported by the absolute URL you pass to fetch).
You also set mode: 'no-cors' which means "Don't throw a security exception for trying to access a cross-origin resource, and don't make the response available to JS".
Consequently, when you try to read the response: You can't.
Set the mode to "cors" and change the Node.js code to follow the CORS specification to grant permission to the page trying to read the data.
I try to wrap my mind around nodejs at the moment.
There is nothing particular to Node.js here. The problems are related to security restrictions on what JavaScript running in the browser can do unless granted permission by the HTTP server.
To not completely mess up my question, I post my solution for problem number one as separate answer:
SOLUTION 1) The sever does not get the body (req.body is undefined)
As request is a stream, I need to treat it like one (notice "req.on('data'...)
This is how the server works as expected:
// request needed modules
const http = require('http');
// init server
let server = http.createServer(handler);
server.listen(8099);
// server logic
function handler (req, res) {
// Set CORS headers
let headers = {
'Access-Control-Allow-Origin' : '*',
'Access-Control-Allow-Methods' : 'POST, OPTIONS',
'Access-Control-Allow-Headers' : 'Content-Type, Accept'
};
res.writeHead(200, headers);
if(req.method == 'POST'){
var body = '';
req.on('data', data => {
body += JSON.parse(data).aString;
});
req.on('end', () => {
res.end(body.toString().toUpperCase());
});
} else if (req.method == 'OPTIONS'){
res.end();
}
}

Categories