I did a POST request, and I got a signal via console.log, but my array doesn't get updated. What am I missing?
CLIENT:
const handleClick = () => {
console.log("i was clicked")
fetch("http://localhost:5000/", {
method: "post",
headers: {'Accept': 'application/json',"Content-Type": "application/json"},
body: JSON.stringify(testPost),
}).then((res) => res.json())
.then(data =>{console.log("success", data)})
.catch((err) =>{console.log("rejected", err)})
};
SERVER:
let data = {
'skills': ["breathing ", "pooping"],
'awards': 2
}
app.get("/", (req, res) => {
res.json(data);
});
app.post("/", (req, res) => {
const {body} = req;
res.json(data)
console.log(body)
console.log(data)
});
I use express, cors, body-parser on the server. On the client nothing special.
my expecation: { skills: [ 'breathing ', 'pooping', 'eating' ], awards: 2 }
my results: { skills: [ 'breathing ', 'pooping' ], awards: 2 }
First, I don't know what kind of data you send to your endpoint.
So I think you send the whole object.
let data = {
'skills': ["breathing ", "pooping"],
'awards': 2
}
// ...
app.post("/", (req, res) => {
const {body} = req;
data = body // this is what you are missing
res.json(data)
console.log(body)
console.log(data)
});
What you need is to update your data object on your post request. I am assuming from your comment that your request body is like this {skills: ["eating"]}. So you may update your post api like this.
let data = {
'skills': ["breathing ", "pooping"],
'awards': 2
}
app.get("/", (req, res) => {
res.json(data);
});
app.post("/", (req, res) => {
// update skills array
data.skills = [...data.skills, ...req.body.skills];
res.json(data)
console.log(body)
console.log(data)
});
this should provide your expected result.
Related
I made get request to Serp api, but learned that it is not possible to directly make fetch to Serp from React application, so I created local server and wrote logic for it, then I tested it with Postman and everything is fine. Then I had problems with CORS, I(guess) fixed them, but now I receive rejected promise on response and can't get rid of this. It gives
Unexpected end of input
Here is my server:
const SerpApi = require('google-search-results-nodejs');
const search = new SerpApi.GoogleSearch("myApiKey");
const express = require('express');
const app = express();
var allowCrossDomain = function (req, res, next) {
res.header('Access-Control-Allow-Origin', "*");
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type');
next();
}
app.get('/:id', function (req, res) {
console.log("Made request");
const searchText = req.params.id;
const params = {
q: searchText,
tbm: "shop",
};
const callback = function (data) {
const objects = [...data["shopping_results"]];
console.log("call back worked");
if (!objects) {
console.log("ERROR 404");
res.status(404).send();
}
res.status(200).send(objects);
};
// Show result as JSON
search.json(params, callback);
});
app.use(allowCrossDomain);
app.listen(3001, function () {
console.log("App is listening for queries");
})
and my fetch:
import updateOnSearchRequest from '../redux/actions/updateOnSearchRequest';
export default function searchRequestToApi(queryText, dispatch) {
fetch(`http://localhost:3001/${queryText}`, {
mode: 'no-cors',
})
.then(res => console.log(res.json()))
.then(data => data ? dispatch(updateOnSearchRequest(data)) : {});
}
I receive error at console.log(res.json()) even though server works fine and doesnt give any errors
First of all, you need to remove mode: "no-cors", as mentioned in this answer, using it will give you an opaque response, which doesn't seem to return data in the body.
Second, move your app.use(allowCrossDomain); to the top so it's higher than app.get("/:id", function (req, res) {....
And lastly, you must remove console.log from .then(res => console.log(res.json())).
In summary, your server should be:
const SerpApi = require("google-search-results-nodejs");
const search = new SerpApi.GoogleSearch("myApiKey");
const express = require("express");
const app = express();
var allowCrossDomain = function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE");
res.header("Access-Control-Allow-Headers", "Content-Type");
next();
};
app.use(allowCrossDomain);
app.get("/:id", function (req, res) {
console.log("Made request");
const searchText = req.params.id;
const params = {
q: searchText,
tbm: "shop",
};
const callback = function (data) {
const objects = [...data["shopping_results"]];
console.log("call back worked");
if (!objects) {
console.log("ERROR 404");
res.status(404).send();
}
res.status(200).send(objects);
};
// Show result as JSON
search.json(params, callback);
});
app.listen(3001, function () {
console.log("App is listening for queries");
});
And your fetch should be:
fetch(`http://localhost:3001/${queryText}`)
.then(res => res.json())
.then(data => data ? dispatch(updateOnSearchRequest(data)) : {});
So I have something like this in one of my controllers:
module.exports.authToken = (req, res, next) => {
const token = req.cookies.jwt;
//console.log(token);
if (!token) {
return res.sendStatus(403);
}
try {
const data = jwt.verify(token, "secret token");
console.log(data);
req.userId = data.id;
return next();
} catch {
return res.sendStatus(403);
}
};
and it's called by a route:
router.get("/protected", authController.authToken, (req, res) => {
return res.json({ user: { id: req.userId, role: req.userRole } });
});
and I want to get a JSON response of that route in one of my other controllers. I tried some things but none of it worked.
What I would do is abstract the response out to a function for re-use:
// the function will just return the data without writing it to the response
function protectedRoute(req) {
return {user: {id: req.userId, role: req.userRole}};
}
router.get("/protected", authController.authToken, (req, res) => {
// in the actual handler you can return the response
return res.json(protectedRoute(req));
});
// make sure the middleware is still being run
router.get("/other_route", authController.authToken, (req, res) => {
// use the same function to get the response from /protected
const protectedResponse = protectedRoute(req);
// do stuff with it
});
I want to send an id from React to Node.js.
Here is React code:
...
<Button className='button' onClick={() => toggleButton(data)}>click</Button>
...
const toggleButton = (data) => {
fetch('http://localhost:9000/testAPI', {
method: 'POST',
body: {
id: data.id,
},
})
.then(function (response) {
return response.json();
})
.then(function (body) {
console.log(body);
});
};
and here is in Node.js (testAPI.js):
var express = require('express');
var router = express.Router();
router.post('/', function (req, res) {
console.log('req: ', req);
console.log('res: ', res);
});
it prints a lot of data in terminal log but nowhere the information sent from React.
Any suggestions?
check the root in your nodejs code. it should '/testAPI'
router.post('/testAPI', function (req, res) {
console.log('req: ', req);
console.log('res: ', res);
});
I'm a Node, web dev and programming beginner following 'Get Programming with Node.js' by Jonathan Wexler. I've worked up to the end of the section on routing in vanilla Node, with the following code in main.js:
http = require("http"),
httpStatusCodes = require("http-status-codes"),
fs = require("fs"); // This is a node js core module which interacts with the filesystem on behalf of the app.
(router = require("./router")),
(plainTextContentType = {
"Content-Type": "text/plain",
}),
(htmlContentType = {
"Content-Type": "text/html",
}),
(pngContentType = {
"Content-Type": "image/png",
}),
(customReadFile = (file, res) => {
fs.readFile(`./${file}`, (errors, data) => {
if (errors) {
console.log("Error reading the file...");
}
res.end(data);
});
});
router.get("/", (req, res) => {
res.writeHead(httpStatusCodes.OK, plainTextContentType);
res.end("INDEX");
});
router.get("/index.html", (req, res) => {
res.writeHead(httpStatusCodes.OK, htmlContentType);
customReadFile("views/index.html", res);
});
router.get("/image.png", (req, res) => {
res.writeHead(httpStatusCodes.OK, pngContentType);
customReadFile("public/images/image.png");
});
router.post("/", (req, res) => {
res.writeHead(httpStatusCodes.OK, plainTextContentType);
res.end("POSTED");
});
http.createServer(router.handle).listen(3000);
console.log(`The server is listening on port number: ${port}`);
It works just fine for loading the /index.html file, but when I try to load /image.png (stored in the correct folder, public/images/image.png) it always crashes with the error message TypeError: Cannot read property 'end' of undefined.
This happens no matter what image I use and happens also if I move the image to another folder, such as views. I have also tried writing res.write(data); res.end() instead, also to no avail. I have also tried using an async function within fs.readFile but I don't think that should be the issue here, because fs.readFile should itself execute synchronously within the function if I understand correctly.
Edit
The code for router.js, in case that helps:
const httpStatus = require("http-status-codes"),
htmlContentType = {
"Content-Type": "text/html",
},
routes = {
GET: {
"/info": (req, res) => {
res.writeHead(httpStatus.OK, {
"Content-Type": "text/plain",
});
res.end("Welcome to the Info Page!");
},
},
POST: {},
};
exports.handle = (req, res) => {
try {
if (routes[req.method][req.url]) {
routes[req.method][req.url](req, res);
} else {
res.writeHead(httpStatus.NOT_FOUND, htmlContentType);
res.end("<h1>No such file exists</h1>");
}
} catch (ex) {
console.log("error: " + ex);
}
};
exports.get = (url, action) => {
routes["GET"][url] = action;
};
exports.post = (url, action) => {
routes["POST"][url] = action;
};
You have to pass the res object as a second argument to your customReadFile function to make it work. What you have:
router.get("/image.png", (req, res) => {
res.writeHead(httpStatusCodes.OK, pngContentType);
customReadFile("public/images/image.png"); // <-- 2nd arg missing
});
What you want to have:
router.get("/image.png", (req, res) => {
res.writeHead(httpStatusCodes.OK, pngContentType);
customReadFile("public/images/image.png", res); // <-- 2nd arg added
});
Trying to figure out how to implement this request and response scenario with javascript's fetch() and an express server.
here's the server:
var express = require('express'),
stripeConnect = require('./routes/connect'),
cors = require('cors'),
bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(cors());
app.use(function (req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Credentials', 'true');
next();
});
app.use('/connect', connect);
app.listen(process.env.PORT || 5000);
here's routes/connect:
const express = require('express');
const router = express.Router();
const admin = require('firebase-admin');
admin.initializeApp({
credential: admin.credential.cert({
projectId: process.env.projectId,
clientEmail: process.env.clientEmail,
privateKey: process.env.privateKey.replace(/\\n/g, '\n'),
clientId: process.env.clientId
}),
databaseURL: process.env.databaseURL
});
const STRIPE_SK = 'sk_test_KEY';
const stripe = require('stripe')(STRIPE_SK);
// #route POST /stripeConnect/link
// #desc save stripe user account id to their firebase profile
// #access public
router.post('/link', (req, res) => {
console.log('\nLINK-REQUEST-BODY => ');
console.log(req.body);
return admin
.firestore()
.collection('users')
.doc(req.body.docId)
.update({ stripeId: 'test_Id' })
.then((success) => {
console.log('Firestore Update: Success');
res.json({ msg: 'Stripe account ID added to Slide profile.' });
})
.catch((err) => {
console.log('Firestore Update: Fail, Error: ' + err.message);
res.json({ msg });
});
});
module.exports = router;
here's the fetch POST:
function submit() {
$("#progress-label").text("Working...")
const request = {
method: "POST",
body: JSON.stringify({
docId: $('#id').val(),
stripeId: USER_ID
}),
mode: 'cors',
headers: { 'Content-Type': 'application/json'}
}
fetch(SERVER_URL + "/link", request).then(res => {
console.log("res => " + res)
console.log("res.json() => "+ res.json())
console.log("JSON.stringify(res.json()) => "+ JSON.stringify(res.json()))
console.log("res.data => " + res.data)
console.log("res.msg" => + res.msg
}).catch(err => {
document.getElementById("label").innerHTML = res.json()
})
}
The express server logs Firebase Update Success
the front end logs:
res => [object Response]
res.json() => [object Promise]
JSON.stringify(res.json()) => {}
res.data => undefined
res.msg => undefined
Just trying to figure out how to properly get this response from express. Not sure what all of these log-symptoms are telling me. just figured id log all the different ways I could think of handling the response object.
What do I need to do to get the response data?
Your .then() function is just a promise because your receiving it as soon as you get the headers from the request, you need to send the response back (res.send()) in the .then() of the res.json() because it is also a promise. so that modify your routes/connect as per below.
router.post('/link', (req, res) => {
console.log('\nLINK-REQUEST-BODY => ');
console.log(req.body);
return admin
.firestore()
.collection('users')
.doc(req.body.docId)
.update({ stripeId: 'test_Id' })
.then((success) => {
console.log('Firestore Update: Success');
res.json().then(data => ({
data: data,
status: response.status
})
).then(res => {
console.log(res.status, res.data)
})
.catch((err) => {
console.log('Firestore Update: Fail, Error: ' + err.message);
res.json({ msg });
});
});