I made my first API with NodeJs
this is what i get if i try to access to the resource from the url of the browser
I succed to access to posts with postman.
Now i tried to set a little call with a graphic site, but I wasn't able to fetch the datas
this is the call that i tried in a saga
export const fetchWrapper = async url => {
var request = new Request({
url: url,
method: "GET"
});
await fetch(request)
.then(res => res.json())
.then(
result => {
return result;
},
error => {
return error;
}
);
};
and this is the saga
export function* getPosts() {
const url = `http://localhost:8080/feed/posts`;
try {
const data = yield call(fetch(url), {method: 'GET'});
console.log('data',)
yield put(getPostsResponse({ data }));
} catch (e) {
console.log("error", e);
}
}
and these are the errors that i have in the console
UPDATE
As suggested in the comment this is my node code
controller/feed.js
exports.getPosts = (req, res, next) => {
res.json({
posts: [
{ id: 1, title: "Titolo 1", description: "descrizione 1" },
{ id: 2, title: "Titolo 2", description: "descrizione 2" },
{ id: 3, title: "Titolo 3", description: "descrizione 3" }
]
});
};
exports.createPosts = (req, res, next) => {
const title = req.body.title;
const description = req.body.description;
const ID = 1234;
res.status(201).json({
message: "success operation",
post: {
id: ID,
title: title,
description: description
}
});
};
route/feed.js
const express = require("express");
const router = express.Router();
const feedController = require("../controllers/feed");
router.get("/post", feedController.getPosts);
router.post("/post", feedController.createPosts);
module.exports = router;
app.js
const express = require('express');
const bodyParser = require("body-parser");
const feedRoute = require('./route/feed');
const app = express();
app.use(bodyParser.json()); //application json
app.use('/feed', feedRoute);
app.listen(8080);
UPDATE
useEffect(() => {
// getPosts();
fetch("http://localhost:8080/feed/post")
.then(resp => resp.json())
.then(data => console.log('data', data));
}, [getPosts]);
also tried this, but nothing, i receive the same error.
Expected behaviour:
I have to do a successful call to the localhost server.
Solution
As ivani suggested i just enabled the CORS, this is the code the code that I added to app.js. Not the best solution, but now i can see the response.
const allowedOrigins = ["http://localhost:3000", "http://localhost:8080"];
app.use(
cors({
origin: function(origin, callback) {
if (!origin) return callback(null, true);
if (allowedOrigins.indexOf(origin) === -1) {
var msg =
"The CORS policy for this site does not " +
"allow access from the specified Origin.";
return callback(new Error(msg), false);
}
return callback(null, true);
}
})
);
As ivani suggested i just enabled the CORS.
I added this to App.js of nodeJs
const allowedOrigins = ["http://localhost:3000","http://localhost:8080"];
app.use(
cors({
origin: function(origin, callback) {
if (!origin) return callback(null, true);
if (allowedOrigins.indexOf(origin) === -1) {
var msg =
"The CORS policy for this site does not " +
"allow access from the specified Origin.";
return callback(new Error(msg), false);
}
return callback(null, true);
}
})
);
Now i can reach the data
this is the entire App.js file
const express = require('express');
const bodyParser = require("body-parser");
const feedRoute = require('./route/feed');
const cors = require("cors");
const app = express();
const allowedOrigins = ["http://localhost:3000", "http://localhost:8080"];
app.use(
cors({
origin: function(origin, callback) {
if (!origin) return callback(null, true);
if (allowedOrigins.indexOf(origin) === -1) {
var msg =
"The CORS policy for this site does not " +
"allow access from the specified Origin.";
return callback(new Error(msg), false);
}
return callback(null, true);
}
})
);
app.use(bodyParser.json()); //application json
app.use('/feed', feedRoute);
app.listen(8080);
Try to add a proxy field to your package.json in your React folder:
"proxy": "http://localhost:8080"
Then, make your requests like that:
// this will also avoids CORS issues
const url = `/feed/posts`;
Request Example:
// Create a state `Array` (or Object) that will hold all your posts
const [posts, setPosts] = useState([])
useEffect(() => {
const getPosts = async () => {
try {
const response = await fetch('/feed/post');
const data = await response.json();
setPosts(data)
} catch(err) {
console.log(err); // failed to fetch
}
}
// Make the request
getPosts()
}, [/* no dependencies */])
return (
// JSX use 'posts' here
)
For me the solution provided by Legeo didn't work, but this more simple solution worked
const cors = require("cors")
app.use(cors())
or this modern
import cors from 'cors';
app.use(cors())
Related
I'm working on a node.js application.
In my application the requests are going through a middleware which checks if the user is authenticated. In my middleware file though, I keep getting the "next is not defined" error back in my client. What might be the issue? I'm adding the App.js and the middleware file in here:
App.js:
const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');
const graphqlHttp = require('express-graphql');
const { sequelize } = require('./models');
const graphqlSchema = require('./graphql/schema');
const graphqlResolver = require('./graphql/resolvers');
const auth = require('./middleware/auth');
// return instance of the app
app = express();
// setting up the cors config
app.use(cors({
origin: '*'
}));
// tell the app to parse the body of the request
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
// tell the app to go through the middleware before proceeding to graphql
app.use(auth);
// setting the graphql route
app.use('/graphql', graphqlHttp({
schema: graphqlSchema,
rootValue: graphqlResolver,
graphiql: true,
formatError(err) {
if (!err.originalError) {
return err;
}
const data = err.originalError.data;
const message = err.message || 'An error occurred.';
const code = err.originalError.code || 500;
return { message: message, status: code, data: data };
}
})
);
app.use((error, req, res, next) => {
const status = error.statusCode || 500;
const message = error.message;
const data = error.data;
res.status(status).json({ message: message, data: data });
});
sequelize.sync({ force: true })
.then(() => {
app.listen(8080);
})
.catch(err => {
console.log(err);
});
the auth.js file (the middleware):
const jwt = require('jsonwebtoken');
module.exports = (req, res, next) => {
const authHeader = req.get('Authorization');
if (!authHeader) {
req.isAuth = false;
return next();
}
const token = authHeader.split(' ')[1];
let decodedToken;
try {
decodedToken = jwt.verify(token, 'somesupersecretsecret');
} catch (err) {
req.isAuth = false;
return next();
}
if (!decodedToken) {
req.isAuth = false;
return next();
}
req.userId = decodedToken.userId;
req.isAuth = true;
next();
};
I'm using the MERN stack to build an application for the first time.
In order to log HTTP requests I use "morgan".
I managed to send data to mongodb which seems to be working fine. The problem is that my post request is not coming through. It says "pending" for 4 minutes, then fails.
Here's what I think is the relevant part of my code:
"server.js":
const express = require("express");
const mongoose = require("mongoose");
const morgan = require("morgan");
const path = require("path");
const cors = require("cors");
const app = express();
const PORT = process.env.PORT || 8080;
const routes = require("./routes/api");
const MONGODB_URI =
"...";
mongoose.connect(MONGODB_URI || "mongodb://localhost/app", {
useNewUrlParser: true,
useUnifiedTopology: true
});
mongoose.connection.on("connected", () => {
console.log("Mongoose is connected.");
});
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cors());
app.use(morgan("tiny"));
app.use("/api", routes);
app.listen(PORT, console.log(`Server is starting at ${PORT}`));
Then I've put my routes into another file "api.js":
const express = require("express");
const router = express.Router();
const Lane = require("../models/lanes");
router.get("/", (req, res) => {
Lane.find({})
.then(data => {
res.json(data);
console.log("Get request successful!");
})
.catch(error => {
console.log("Error: ", error);
});
});
router.post("/save", (req, res) => {
const data = req.body;
const newLane = new Lane();
newLane.collection.insertMany(data, err => {
if (err) {
console.log(err);
} else {
console.log("Multiple docs inserted");
}
});
});
module.exports = router;
I'm using axios to send the request. This happens after submitting a form within my application.
reducer function:
const reducer = (state, action) => {
switch (action.type) {
case "add":
axios({
url: "http://localhost:8080/api/save",
method: "POST",
data: [...state, { id: uuid(), title: action.title, tasks: [] }]
})
.then(() => {
console.log("Data has been sent to the server");
})
.catch(() => {
console.log("Internal server error");
});
return [...state, { id: uuid(), title: action.title, tasks: [] }];
The reducer is being used by my context provider component, which looks like this:
export function LanesProvider(props) {
const [lanes, dispatch] = useReducer(reducer, defaultLanes);
return (
<LanesContext.Provider value={lanes}>
<DispatchContext.Provider value={dispatch}>
{props.children}
</DispatchContext.Provider>
</LanesContext.Provider>
);
}
The "add" method inside my reducer is being called when submitting a form inside another component.
Please let me know if I can add anything to my question that would help.
Thank you in advance!
you are not sending any response back to client. Try to modify post method like
router.post("/save", (req, res) => {
const data = req.body;
const newLane = new Lane();
newLane.collection.insertMany(data, err => {
if (err) {
console.log(err);
res.send(err)
} else {
console.log("Multiple docs inserted");
res.send("Multiple docs inserted")
}
});
});
When i try to make a request to my server the client send two requests, the first with an empty body, and the second with the correct body
this is my server file
const express = require('express');
const app = express();
const server = require('http').createServer(app);
const io = require('socket.io')(server);
const cors = require('cors');
const bodyParser = require('body-parser');
const authMiddleware = require('./app/middlewares/auth.middleware');
const db = require('./config/db');
app.use(authMiddleware);
app.use(cors({ origin: '*' }));
app.use(bodyParser.json());
db.then(res => {
require('./app/routes')(app);
});
server.listen(3210, () => {
console.log('\x1b[0m', 'Backend escutando e enviando na porta 3210');
});
this is the route file
const userController = require('../controllers/user.controller');
module.exports = app => {
app.post('/sign-up', async (req, res) => {
try {
const signUpData = await userController.signUp(req.body);
res.status(200).json(signUpData.user);
} catch (error) {
console.log(error);
res.status(400).json(error);
}
});
app.post('/sign-in', async (req, res) => {
try {
const signInData = await userController.signIn(req.body);
res.header('x-auth-token', signInData.token);
res.status(200).json(signInData);
} catch (error) {
console.log(error);
res.status(400).json(error);
}
});
};
here is my axios configuration on my react project
import axios from 'axios';
export const apiUrl = 'http://localhost:3210';
export const api = axios.create({
baseURL: apiUrl,
headers: {
common: {
'Content-Type': 'application/json'
}
}
});
the function where i do the request
export const signIn = data => {
return api
.post(`/sign-in`, data)
.then(res => {
console.log(res);
})
.catch(err => {
console.log(err);
});
};
This error only occours when the request is made via client, when i
use postman everything works fine
I have created a simple react app. The problem which I'm finding is when I'm hitting the url, in the response, it is showing as buffer, which should not be the case.
My code
index.js
import axios from 'axios';
export const ADD_CART = "ADD_CART";
export const REMOVE_CART = "REMOVE_CART";
export const LOGIN = "LOGIN";
export const BASE_API_URL = "http://localhost:3030";
export function addToCart(item) {
console.log(window.localStorage.getItem('WCToken'))
console.log(window.localStorage.getItem('WCTrustedToken'))
var headers = {
'Content-Type': 'application/json',
'WCToken': window.localStorage.getItem('WCToken'),
'WCTrustedToken': window.localStorage.getItem('WCTrustedToken')
}
axios.post(BASE_API_URL + "/cart", {
orderItem: [
{
productId: item.uniqueID, //working for 12262
quantity: '1'
}
]
}, {headers: headers}).then(res => console.log(res))
.catch(err => console.log(err));
return {
type: ADD_CART,
payload: item
};
}
export function removeFromCart(cartList, id) {
return {
type: REMOVE_CART,
payload: cartList.filter(i => i.uniqueID != id)
};
}
export const login = () => {
return axios.post(BASE_API_URL + "/guestidentity", {}).then(res => {
window.localStorage.setItem("WCToken", res.data.express.WCToken)
window.localStorage.setItem("WCTrustedToken", res.data.express.WCTrustedToken)
return {
type: LOGIN,
payload: {}
}
}).catch(e => {
console.log(e);
return {
type: LOGIN,
payload: {}
}
});
};
server.js
const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');
const Client = require('node-rest-client').Client;//import it here
const app = express();
const helmet = require('helmet');
const morgan = require('morgan');
// enhance your app security with Helmet
app.use(helmet());
// use bodyParser to parse application/json content-type
app.use(bodyParser.json());
// log HTTP requests
app.use(morgan('combined'));
app.use(cors());
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0
app.post('/guestidentity',(req, res) => {
console.log("Hello from Server")
var client = new Client();
// direct way
client.post("https://149.129.128.3:5443/wcs/resources/store/1/guestidentity", (data, response) => {
res.send({ express: data });
});
});
app.post('/cart',(req, res) => {
console.log("Hello from Server")
var client = new Client();
// direct way
client.post("https://149.129.128.3:5443/wcs/resources/store/1/cart", (data, response) => {
res.send({ express: data });
});
});
const port = 3030;
app.listen(port, () => console.log(`Server running on port ${port}`));
I dont know where my code is getting wrong and why buffer is showing in response. Can somebody please guide me on this. Or provide me an insight how to troubleshoot this issue.
You are sending to the client an object with the form:
{
express: data
}
And when you log that on the console you see that data is an object:
{
data: [],
type: "buffer"
}
Which means that your post request inside express is returning that object.
I have created a simple react app. The problem which I'm finding is when I'm hitting the url, in the response, it is showing as buffer, which should not be the case.
My code
index.js
import axios from 'axios';
export const ADD_CART = "ADD_CART";
export const REMOVE_CART = "REMOVE_CART";
export const LOGIN = "LOGIN";
export const BASE_API_URL = "http://localhost:3030";
export function addToCart(item) {
console.log(window.localStorage.getItem('WCToken'))
console.log(window.localStorage.getItem('WCTrustedToken'))
var headers = {
'Content-Type': 'application/json',
'WCToken': window.localStorage.getItem('WCToken'),
'WCTrustedToken': window.localStorage.getItem('WCTrustedToken')
}
axios.post(BASE_API_URL + "/cart", {
orderItem: [
{
productId: item.uniqueID, //working for 12262
quantity: '1'
}
]
}, {headers: headers}).then(res => console.log(res))
.catch(err => console.log(err));
return {
type: ADD_CART,
payload: item
};
}
export function removeFromCart(cartList, id) {
return {
type: REMOVE_CART,
payload: cartList.filter(i => i.uniqueID != id)
};
}
export const login = () => {
return axios.post(BASE_API_URL + "/guestidentity", {}).then(res => {
window.localStorage.setItem("WCToken", res.data.express.WCToken)
window.localStorage.setItem("WCTrustedToken", res.data.express.WCTrustedToken)
return {
type: LOGIN,
payload: {}
}
}).catch(e => {
console.log(e);
return {
type: LOGIN,
payload: {}
}
});
};
server.js
const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');
const Client = require('node-rest-client').Client;//import it here
const app = express();
const helmet = require('helmet');
const morgan = require('morgan');
// enhance your app security with Helmet
app.use(helmet());
// use bodyParser to parse application/json content-type
app.use(bodyParser.json());
// log HTTP requests
app.use(morgan('combined'));
app.use(cors());
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0
app.post('/guestidentity',(req, res) => {
console.log("Hello from Server")
var client = new Client();
// direct way
client.post("https://149.129.128.3:5443/wcs/resources/store/1/guestidentity", (data, response) => {
res.send({ express: data });
});
});
app.post('/cart',(req, res) => {
console.log("Hello from Server")
var client = new Client();
// direct way
client.post("https://149.129.128.3:5443/wcs/resources/store/1/cart", (data, response) => {
res.send({ express: data });
});
});
const port = 3030;
app.listen(port, () => console.log(`Server running on port ${port}`));
I dont know where my code is getting wrong and why buffer is showing in response. Can somebody please guide me on this. Or provide me an insight how to troubleshoot this issue.
You might need to config your client as to parse response as JSON.
var options = {
mimetypes: {
json: ["application/json", "application/my-custom-content-type-for-json;charset=utf-8"]
}
};
var client = new Client(options);