CORS related problem, i cannot proceed to a POST request - node.js

I'm having some troubles trying to make my backend and front communicate to each others (reactjs + vanilla NODEjs), both on different localhost port (4000 and 3000)
I managed to make it work until i wanted to try to add data to my database.
I can GET data with my react app but i can't POST any data.
Here is the code for both sides :
front :
`
const sendData = async (event: any): Promise<void> => {
console.log("hello");
event.preventDefault();
const response = await fetch(`${_DATA_URL_}`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(employeeForm),
});
const data = await response.json();
console.log(data);
};
`
back :
const Router = (req, res) => {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader(
"Access-Control-Allow-Headers",
"Content-Type, Accept, Origin, Authorization"
);
res.setHeader(
"Access-Control-Allow-Methods",
"GET, POST, PUT, DELETE, PATCH, OPTIONS"
);
console.log("hello"); //debug
if (req.method === "GET") {
if (req.url === "/api/employees") {
getEmployees(req, res);
} else if (req.url.match(/\/api\/employees\/(\w{4}-?){3}/)) {
const requestID = req.url.split("/")[3];
getEmployee(req, res, requestID);
} else {
res.statusCode = 404;
res.setHeader("Content-Type", "application/json");
res.end(JSON.stringify({ message: `Error : ${req.url} not found !` }));
}
}
if (req.method === "POST") {
if (req.url === "/api/employees") {
createEmployee(req, res);
} else {
res.setHeader("Content-Type", "application/json");
res.end(JSON.stringify({ message: `Error : ${req.url} not found !` }));
}
}
if (req.method === "DELETE") {
if (req.url.match(/\/api\/employees\/(\w{4}-?){3}/)) {
const requestID = req.url.split("/")[3];
deleteEmployee(req, res, requestID);
} else {
res.statusCode = 404;
res.setHeader("Content-Type", "application/json");
res.end(JSON.stringify({ message: `Error : ${req.url} not found !` }));
}
}
if (req.method === "PUT") {
if (req.url.match(/\/api\/employees\/(\w{4}-?){3}/)) {
const requestID = req.url.split("/")[3];
updateEmployee(req, res, requestID);
} else {
res.statusCode = 404;
res.setHeader("Content-Type", "application/json");
res.end(JSON.stringify({ message: `Error : ${req.url} not found !` }));
}
}
};
i'm pretty sure it comes from react side because posting data works fine when i use POSTMAN, and after a while on localhost i receive this error in the console :
Maybe i'm using cors incorrectly, anyways thanks for your futures answers

I figured it out,
answer here (in french) and here

Related

Get HTTP request body data using Node.js

The frontend is index.html:
axios.post('http://localhost:1337/', {
clientId: document.getElementById('clientId').value,
cmd: document.getElementById('cmd').value,
type: document.getElementById('type').value,
amt: document.getElementById('amt').value,
merchantRef: document.getElementById('merchantRef').value,
channel: document.getElementById('channel').value,
successUrl: document.getElementById('successUrl').value,
failureUrl: document.getElementById('failureUrl').value,
webhookUrl: document.getElementById('webhookUrl').value,
goodsName: document.getElementById('goodsName').value
})
.then(function (response) {
var json = response.data;
document.getElementById('sessionId').innerHTML = json['sessionId'];
SpiralPG.init(json['sessionId']);
})
.catch(function (error) {
console.log(error);
});
The backend is server.js:
http.createServer(async function (req, res) {
try {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Request-Method', '*');
res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET, POST');
res.setHeader('Access-Control-Allow-Headers', '*');
const buffers = [];
for await (const chunk of req) {
buffers.push(chunk);
};
const data = Buffer.concat(buffers).toString();
saleSession(res, data);
}
catch (error) {
console.log(error);
}
}).listen(port);
something inside function saleSession(); in the server.js to get the data from frontend(if I hard code in here, there will be no error, but change to input data from frontend, there will be error):
var merchantRef = JSON.parse(data).merchantRef;
let bodyData =
{
'clientId': JSON.parse(data).clientId,
'cmd': JSON.parse(data).cmd,
'type': JSON.parse(data).type,
'amt': JSON.parse(data).amt,
'merchantRef': merchantRef,
'channel': JSON.parse(data).channel,
'successUrl': JSON.parse(data).successUrl,
'failureUrl': JSON.parse(data).failureUrl,
'webhookUrl': JSON.parse(data).webhookUrl,
'goodsName': JSON.parse(data).goodsName
}
I'm just copy the code in https://nodejs.dev/learn/get-http-request-body-data-using-nodejs, which is node.js office website. Why the output is:
SyntaxError: Unexpected end of JSON input
at JSON.parse (<anonymous>)
at saleSession (C:\Users\JoeChan\Desktop\my-nodejs2\server.js:41:28)
at Server.<anonymous> (C:\Users\JoeChan\Desktop\my-nodejs2\server.js:104:9)
at processTicksAndRejections (node:internal/process/task_queues:96:5)

Cross Server user not receiving the actual value of cookies

I am trying to send/retrieve cookies from one system to another system.
Here is my FE code (Angular 4) for setting a cookie
document.cookie = 'student_exists=true;SameSite=None;Secure'
// it will be true or false depending upon whether the student exists or not.
this is my route in node.js -> xx.com/api/retrievecookie
This is my function
retrievecookie () {
try {
let student_exists = false;
if (req.cookies && req.cookies.student_exists &&
req.cookies.student_exists === 'true') {
student_exists = true
}
const data = {'student_exists': student_exists};
res.json(data);
} catch (e) {
console.log(e);
res.send({'error': 'error in your request'});
}
}
Here is my index file (node js)
const cookieParser = require('cookie-parser');
app.use(function (req, res, next) {
console.log(req);
const origin = req.headers.origin;
if (req.url === '/api/studentprofile/verify') {
res.setHeader('Access-Control-Allow-Origin', origin);
} else {
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:4200');
}
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');
res.setHeader('Access-Control-Allow-Credentials', true);
next();
});
When I am hitting the URL & same browser from my own system, I am getting the true values i.e. either true or false.
When the other user with different server or browser, ther user is always getting false,
Here is other user's code
> $.ajax({
> type: "GET",
> url: "xx.com/api/retrievecookie",
> xhrFields: {
> withCredentials: true
> },
> success: function(data) {
> console.log(data);
> },
> error: function(data) {
> alert(data);
> }
});
please help me fix this issue.

"\" in JSON response

So my app gets data from my database but it send a response with " \ "
Express response
[
{
"ID": "account-saassan",
"data": "{\"uuid\":\"saassan\",\"username\":\"sasasasasa\"}"
}
]
Console output:
[
{
ID: 'account-saassan',
data: '{"uid":"saassan","username":"sasasasasa"}'
}
]
Code:
const UserData = new db.table("userdata")
app.use((req, res, next) => {
res.append('Access-Control-Allow-Origin', ['*']);
res.append('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.append('Access-Control-Allow-Headers', 'Content-Type');
next();
});
app.get("/list", (request, response) => {
let data = UserData.all()
console.log(data)
response.type('json');
response.json(data)
// I've tried with response.send too. And without response.type
})
app.listen(8080)
Why does it add "" in the response and how do I fix it?
Try to using JSON.stringify
response.json(JSON.stringify(data))
Add please add this :
response.setHeader('Content-Type', 'application/json');

Acessing request body without using Express Nodejs

So I am trying to access the body of a request I am sending. I don't want to incorporate Express for this project. I understand that I essentially have to stream the body in from the incoming request, however it seems that my approach isn't pulling any data from the request. Here is what I have
The request
var query = document.getElementById('search').value;
console.log(query);
axios({
method: 'get',
url: url,
headers: {},
data: {
query: query
}
}).then((response) => {
if(response.status == 200){
console.log(response);
this.tweet = response;
}
}).catch((error) => {
console.log(error);
});
Where I am handling the request
http.createServer((req, res ) => {
//Setting CORS Headers
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Request-Method', '*');
res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET');
res.setHeader('Access-Control-Allow-Headers', '*');
if ( req.method === 'OPTIONS' ) {
res.writeHead(200);
res.end();
return;
}
else if(req.url == "/search"){
let body = 'Our Data: ';
req.on('data', chunk => {
body += chunk.toString();
});
req.on('end', () => {
console.log(body);
});
//console.log(data);
callTweetAPI.callTweetAPI(function(response) {
res.write(JSON.stringify(response));
res.end();
});
}
}).listen(port);
The output I expect would be the data I sent in the axios request so 'query', but I end up with blank output. It seems that the request being sent through doesn't have a data block available?

How to make something like remote method on loop-back middleware?

In fallowing code i want to make something like remote method on middleware in loopback to post values to calculate for example:
in app :
submitForm() {
let headers = new Headers(
{
'Content-Type': 'application/json',
'Accept': 'application/json'
});
let options = new RequestOptions({ headers: headers });
let data = JSON.stringify({
Value1: this.form.value1,
Value2: this.form.value2,
Value3: this.form.value3
});
console.log(data);
let url = 'http://localhost:3000/calculate';
console.log(url);
return new Promise((resolve, reject) => {
this.http.post(url, data, options)
.toPromise()
.then((response) => {
console.log('API Response : ', response.status);
resolve(response.json());
})
.catch((error) => {
console.error('API Error : ', error.status);
console.error('API Error : ', JSON.stringify(error));
reject(error.json());
});
});
}
and in remote method or anything like that, I used such this code but totally fails:
module.exports = function () {
accepts: [{arg: 'val1', type: 'number'},{arg: 'val2', type: 'number'}],
returns: {arg: val1+val2, type: 'number'},
http: {path: '/calculate', verb: 'get'}
});
};
Example remote method that I used correctly
module.exports = function (TeamRole) {
TeamRole.getUsers = function (id, cb) {
TeamRole.find({
where: {
teamId: id
}
}, function (err, users) {
cb(null, users);
});
};
TeamRole.remoteMethod('getUsers', {
accepts: {
arg: "id",
type: "string",
required: true
},
returns: {
arg: 'users',
type: 'Array'
},
http: {
path: '/:id/users',
verb: 'get'
}
});
}
As above example you can define remote method correctly to achieve you task.
cheers.
This is my solution for my problem:
As you can see there is no parameters shown on URL and i think this may be secure I'm not expert one but I guess help to you:
module.exports = function(server) {
const https = require('https');
var request = require('request');
return function verification(req, res, next) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
res.setHeader('Access-Control-Allow-Credentials', true);
var request;
var response;
var body = '';
// When a chunk of data arrives.
req.on('data', function (chunk) {
// Append it.
body += chunk;
});
// When finished with data.
req.on('end', function () {
// Show what just arrived if POST.
if (req.method === 'POST') {
console.log(body);
}
// Which method?
switch (req.method) {
case 'GET':
Verify url and respond with appropriate data.
handleGet(req, res);
Response has already been sent.
response = '';
break;
case 'POST':
// Verify JSON request and respond with stringified JSON response.
response = handlePost(body);
break;
default:
response = JSON.stringify({ 'error': 'Not A POST' });
break;
}
// Send the response if not empty.
if (response.length !== 0) {
res.write(response);
res.end();
}
// Paranoid clear of the 'body'. Seems to work without
// this, but I don't trust it...
body = '';
});
// If error.
req.on('error', function (err) {
res.write(JSON.stringify({ 'error': err.message }));
res.end();
});
//
};
function handlePost(body) {
var response = '';
var obj = JSON.parse(body);
// Error if no 'fcn' property.
if (obj['fcn'] === 'undefined') {
return JSON.stringify({ 'error': 'Request method missing' });
}
// Which function.
switch (obj['fcn']) {
// Calculate() requres 3 arguments.
case 'verification':
// Error if no arguments.
if ((obj['arg'] === 'undefined') || (obj['arg'].length !== 3)) {
response = JSON.stringify({ 'error': 'Arguments missing' });
break;
}
// Return with response from method.
response = verification(obj['arg']);
break;
default:
response = JSON.stringify({ 'error': 'Unknown function' });
break;
}
return response;
};
function verification(arg) {
var n1 = Number(arg[0]);
var n2 = Number(arg[1]);
var n3 = Number(arg[2]);
var result;
// Addem up.
result = n1 + n2 + n3;
// Return with JSON string.
return JSON.stringify({ 'result': result });
};
};

Resources