Nextjs not able to receive data from expressjs API in correct format - express

ive got a page which i call an api through getserversideprops to basically get all the data from a table. it used to work fine, but suddenly when i runned it today an error occured which i dont know the cause is. this is the response im getting when i console log the response
what i tried on my own and noticed to "help" was reducing the amount of columns that the API was selecting. For the api i used knex and express. this was the original code that used to work but now does not.
try{
let data = "";
await db.transaction(async (t)=>{
data = await db('sales').transacting(t)
.join('users','users.id','sales.cashier_id')
.join('customer','customer.customer_id','sales.customer_id')
.select('customer.name as customer_name','sales.sales_id','sales.date','sales.payment_type','sales.payment_status','sales.customer_id','sales.transaction_total','sales.total_paid','users.name','sales.shipment_fee','sales.days','sales.sale_type')
})
return data
}catch(e){
console.log(e);
throw e;
}
what i tried was reducing the amount of select columns to i think 5 or 6, but definitely if the amount of columsn i use is under a limit it works. like
try{
let data = "";
await db.transaction(async (t)=>{
data = await db('sales').transacting(t)
.join('users','users.id','sales.cashier_id')
.join('customer','customer.customer_id','sales.customer_id')
.select('customer.name as customer_name','sales.sales_id','sales.transaction_total','sales.date','sales.payment_type')
})
return data
}catch(e){
console.log(e);
throw e;
}
these are the attributes of my table
this is the server.js file of my expressjs
const compression = require('compression');
const express = require("express");
const app = express();
const fs = require('fs');
const http = require('http')
const https = require('https')
const PORT = process.env.PORT || 8000;
var cors = require('cors')
const mainRoutes = require('./api/v1/routes/index')
const cookieParser = require("cookie-parser");
app.use(compression());
app.use(cors( {origin: 'http://localhost:3000',credentials: true}))
// app.use(cors());
app.use(express.json());
// app.use(express.urlencoded({ extended: true }));
app.use(cookieParser());
// Main Routes
app.use("/api/v1", mainRoutes,(req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
next();
});
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}.`);
});
this is how im calling the api from next
export async function getServerSideProps(context) {
try{
const res = await axios.get("/sales/get-all");
const data = await res.data
return { props: { data } }
}catch(err){
const data = "error"
return { props: { data} }
}
}
where i declared default url of the axios at the app.js file of next
import '../styles/globals.css'
import axios from 'axios';
axios.defaults.baseURL = "http://localhost:8000/api/v1/"
function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />
}
export default MyApp
im not quite sure what the problem is so pardon if the title of the question is not according to the problem i have.
EDIT:
i moved the api to a useeffect call, its now working. but why isnt it working in getserversideprops?

Related

How do I get back data from a database using express.js without the result being undefined

`I've been trying to display a database product with react but none of my approaches seem to work.
This is my node.js/express code :
const express = require('express');
const database = require('./config/database');
const bodyParser = require('body-parser');
const cors = require('cors');
const PORT = 3001;
const app = express();
app.use(express.json());
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.get('/products/:productId', (req, res) => {
console.log('request recieved');
const productId = req.params.productId;
const query = `SELECT * FROM products WHERE product_id = ${productId}`;
database.query(query, (err, result) => {
if (err) console.log(err);
console.log(result);
res.send(result);
});
});
app.listen(PORT, 'localhost');
I tried to fetch and log it with axios but the results are undefined :
const productId = params.productId;
const url = `/product/${productId}`;
const [{data, loading, error}] = useAxios(url);
console.log(data);
I also tried the regular approach :
const fetchProduct = async (url) => {
try {
const response = await fetch(url);
console.log(response);
const data = await response.json();
console.log(data);
} catch(err) {
console.log(err);
}
return data;
}
const product = fetchProduct(url);
console.log(product);`
Some help would be appreciated
What if you create an arrow-function that it returns a Promise
const getById = (productId) => {
const query = `SELECT * FROM products WHERE product_id = ${productId}`;
return new Promise((resolve, reject) => {
database.query(query, (err, result)=> {
err ? reject(err): resolve(result)
})
})
}
as our getById arrow-function returns a promise we need to async/await on it, so the app.get will be like this
app.get('/products/:productId', async(req, res) => {
console.log('request recieved');
const productId = req.params.productId;
const product = await getById(productId)
res.status(200).send(product)
});
One more thing, in your code you wrote
app.use(express.json());
and
app.use(bodyParser.json());
those two instruction do the SAME THING, so you need to delete one of them, and it better be the bodyParser one, because the body-parser is just deprecated and you don't need to install it, you just need to add
app.use(express.json())
app.use(express.urlencoded({ extended: true }))

Express. Failed to load resource: the server responded with a status of 404

I am trying to make a post request using router.post and I keep getting " the server responded with a status of 404.
I have a routes folder with the file usersRoute.js :
const express = require("express");
const router = express.Router();
const User = require("../models/userModel");
router.post("/login", async(req, res) => {
const { username, password } = req.body;
try {
const user = await User.findOne({ username, password });
if (user) {
res.send(user);
} else {
return res.status(400).json(error);
}
} catch (error) {
return res.status(400).json(error);
}
});
router.post("/register", async (req, res) => {
try {
const newuser = new User(req.body);
await newuser.save();
res.send("User registered successfully");
} catch (error) {
return res.status(400).json(error);
}
});
module.exports = router;
I'm also using this method to make a get request to another endpoint in a carsRoute.js file which looks like this (the get request works) :
const express = require("express");
const router = express.Router();
const Car = require("../models/carModel");
router.get("/getallcars", async(req,res) => {
try {
const cars = await Car.find()
res.send(cars)
} catch (error) {
return res.status(400).json(error);
}
})
module.exports = router;
Finally, I export them into server.js which looks like this :
const express = require('express');
const app = express();
const port = process.env.port || 5000;
const dbConnect = require('./db');
app.use(express.json())
app.use('/api/cars/' , require('./routes/carsRoute'))
app.use('/api/users/', require('./routes/usersRoute'))
app.get('/', (req,res) => res.send('Hello World') )
app.listen(port, () => console.log(`Node Js Server Started on port ${port}`))
I do not think i missed any "/" or have any additional ones.

Nuxt/Express API is returning in console but not browser

I'm quite new to this whole backend business and I'm wondering if anyone can see where I'm going wrong. I've got an express server in my Nuxt app which is serving out an API. When I run the localhost:3000/api/salesforce/:id route - my vscode terminal generates a response - but it doesn't show up on the browser. Which in turn makes it inaccessible to Nuxt.
In my nuxt.config.js:
serverMiddleware: {
'/api': '~/api'
},
/api/index.js:
const express = require('express')
// Create express instance
const app = express()
// Require API routes
const users = require('./routes/users')
const test = require('./routes/test')
const salesforce = require('./routes/salesforce')
// Import API Routes
app.use(users)
app.use(test)
app.use(salesforce)
// Export express app
module.exports = app
// Start standalone server if directly running
if (require.main === module) {
const port = process.env.PORT || 3001
app.listen(port, () => {
// eslint-disable-next-line no-console
console.log(`API server listening on port ${port}`)
})
}
Then in /api/routes/salesforce.js:
const e = require('express')
const { Router } = require('express')
const router = Router()
const jsforce = require('jsforce');
// require the .env file for login
require('dotenv').config();
const { SF_USERNAME, SF_PASSWORD, SF_TOKEN, SF_LOGIN_URL } = process.env;
if (!(SF_USERNAME && SF_PASSWORD && SF_TOKEN && SF_LOGIN_URL)) {
console.error(
'Cannot start app: missing mandatory configuration. Check your .env file.'
);
process.exit(-1);
}
const conn = new jsforce.Connection({
loginUrl: SF_LOGIN_URL
});
conn.login(SF_USERNAME, SF_PASSWORD + SF_TOKEN, err => {
if (err) {
console.error(err);
process.exit(-1);
}
});
// get OPPORTUNITY specific
router.get('/salesforce/:id', function (req, res, next) {
const id = req.params.id
console.log(req.params.id)
const sfData = conn.query(`SELECT Id, Name, StageName FROM Opportunity WHERE Name = '` + id + `'`, (err, res)=>{
if(err){
console.log(err)
return "error";
} else {
console.log(res.records[0])
let sanitisedData = res.records[0]
return sanitisedData;
}
})
res.json(sfData.json)
})
If anyone can tell me where I'm going wrong that would be greatly appreciated, I'm kind of stuck here.

Run socket.io from an express route

I have researched on this but nothing seems to satisfy my need. I have an express route connected to a mongodb. Below is part of the code.
const express = require('express');
const socketIo = require("socket.io");
const dbconnect = require("./models");
const handle = require("./handlers");
const routes = require("./routes");
const app = express();
app.use('/messages', routes.messages);
const PORT = 3000;
const server = app.listen(3000, function() {
console.log(`Listening on 3000`);
dbconnect().then(() => {
console.log("MongoDb connected");
});
});
const io = socketIo(server);
io.on('connection', function(client) {
console.log('Connected...');
});
My route looks like this:
const router = require('express').Router();
const handle = require('../handlers/messages');
router.post('/unread_messages', handle.unread_messages);
module.exports = router;
My handler looks like this:
const db = require("../models");
exports.unread_messages = async (req, res, next) => {
try {
const unreadmessages = await db.messages.countDocuments({ $and: [{receiver: req.body.receiver},
{ messageread: false }]});
return res.json({ unreadmessages });
} catch (err) {
return next({ status: 400, message: `Cannot get unread messages ${err}` });
}
};
I would like to add socket to the "/unread_messages" route so that I get an update of the count of unread messages in realtime. How do I do that?

Trying to use express middleware to serve third party API requests

Sorry if I posted this incorretly, it is my first question on Stack Overflow. I am currently trying to use express to serve third party API requests to my React front-end. This is because the steam api I use throws me a CORS error when requesting in the client-side. I tried to route the requests to my controller which makes the axios call, but I have had no luck. Not sure if I am doing something completely incorrect.
here is my server.js
const app = require('./app.js');
const PORT = process.env.PORT || 3005;
app.listen(PORT, () => console.log(`Listening on port: ${PORT}`))
and here is my app.js
const express = require('express');
const cors = require('cors')
const app = express();
app.use(cors())
module.exports = app
my routes:
const { Router } = require('express')
const controllers = require('../controllers')
const router = Router()
router.get('/', (req, res) => res.send('This is root!'))
router.get('/applist', controllers.getAllSteamGames)
router.get('/game/:id', controllers.getSingleGameSteam )
router.get('/gameSpy/:id', controllers.getSingleGameSpy)
module.exports = router
and lastly my controller:
const axios = require('axios');
const getAllSteamGames = async () => {
try {
const resp = await axios.get('https://api.steampowered.com/ISteamApps/GetAppList/v2?applist')
return resp.data
} catch (error) {
console.log(error)
throw error
}
}
Thank you for your help and time.
You aren't doing anything to send a response back to the client. If we look at the /applist route:
router.get('/applist', controllers.getAllSteamGames)
const axios = require('axios');
const getAllSteamGames = async () => {
try {
const resp = await axios.get('https://api.steampowered.com/ISteamApps/GetAppList/v2?applist');
return resp.data
} catch (error) {
console.log(error)
throw error
}
}
All, your getAllSteamGames() function does is return a promise that resolves to a value (remember all async functions return a promise). It doesn't send a response back to the client.
Then, if you look at the actual route handler, it doesn't send a response back to the client either. So, you get the request and never send a response. The client never gets a response.
What I would suggest is that you just send a response in your controller. It's already passed (req, res) as arguments to the function so you can use them.
router.get('/applist', controllers.getAllSteamGames)
const axios = require('axios');
const getAllSteamGames = async (req, res) => {
try {
const resp = await axios.get('https://api.steampowered.com/ISteamApps/GetAppList/v2?applist');
res.json(resp.data);
} catch (error) {
// send error status upon error
console.log(error);
res.sendStatus(500);
}
}