We're using Nextjs/Reactjs as our FE and we have a server.js file that will allow us to upload image on public/images/uploads but for some reason whenever we run the server we are getting error Cannot GET /
Here is the code we have on server.js
const { createServer } = require('http');
const { parse } = require('url');
const next = require('next');
const express = require('express');
const multer = require('multer');
const cors = require('cors');
const port = parseInt(process.env.PORT, 10) || 3000
const dev = process.env.NODE_ENV !== 'production'
var app = next({ dev });
const handle = app.getRequestHandler();
const appExpress = express();
app.prepare().then(() => {
createServer((req, res) => {
const parsedUrl = parse(req.url, true)
const { pathname, query } = parsedUrl
if (pathname === '/a') {
app.render(req, res, '/a', query)
} else if (pathname === '/b') {
app.render(req, res, '/b', query)
} else {
handle(req, res, parsedUrl)
}
}).listen(port, err => {
if (err) throw err
console.log(`> Ready on http://localhost:${port}`)
})
})
appExpress.use(express.static('public'))
let storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, 'public/images/uploads')
},
filename: (req, file, cb) => {
cb(null, Date.now() + '-' + file.originalname)
}
});
const upload = multer({ storage })
appExpress.use(cors());
appExpress.post('/upload', upload.single('image'), (req, res) => {
if (req.file)
res.json({
imageUrl: `images/uploads/${req.file.filename}`
});
else
res.status("409").json("No Files to Upload.");
});
const PORT = 5000;
appExpress.listen(PORT);
console.log('api running on port: ' + PORT);
These are the scripts include on our package.json
"dev": "next",
"build": "next build && next export",
"start": "next start",
"server": "node server.js"
},
Hoping to get some answers and recommendations. This codes are working locally without any issues
You need to add a route for the GET / like this:
appExpress.get('/', (req, res) => {
res.json({server: 'Running..!'});
});
Related
//Error
GET http://localhost:8080/Uploads/2022-01-05T15-45-33.363Z-portfolio.png net::ERR_BLOCKED_BY_RESPONSE.NotSameOrigin 200
Files and other fields were saved database but I could not fetch the images server while I can reach other fields.
//Server
*Client APIs*
const create = async (credentials, restaurant) => {
try {
let response = await fetch(config.ServerURI + "/restaurants", {
method: "POST",
headers: {
"Authorization": "Bearer " + credentials.t,
},
body: restaurant,
});
return await response.json();
} catch (error) {
console.log(error);
}
};
const list = async (signal) => {
try {
let response = await fetch(config.ServerURI + "/restaurants", {
method: "GET",
signal: signal,
});
return await response.json();
} catch (error) {
console.log(error);
}
};
//Multer middleware
const multer = require('multer');
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, './Uploads');
},
filename: function (req, file, cb) {
cb(
null,
`${new Date().toISOString().replace(/:/g, '-')}-${
file.originalname
}`
);
},
});
const filefilter = (req, file, cb) => {
if (
file.mimetype === 'image/png' ||
file.mimetype === 'image/jpg' ||
file.mimetype === 'image/jpeg'
) {
cb(null, true);
} else {
cb(null, false);
}
};
const upload = multer({ storage: storage, fileFilter: filefilter });
//Server
const create = async (req, res) => {
const user = req.auth._id;
let filesArray = [];
req.files?.forEach((element) => {
const file = {
fileName: element.originalname,
filePath: element.path,
fileType: element.mimetype,
fileSize: fileSizeFormatter(element.size, 2),
};
filesArray.push(file);
});
const { name, location, cost, rating } = req.body;
const { restaurantId } = await createRestaurant(
name,
location,
cost,
rating,
filesArray,
user
);
res.json({ restaurantId });
};
// app.js
require('dotenv').config();
require('express-async-errors');
// const path = require('path');
// extra security packages
const helmet = require('helmet');
const cors = require('cors');
const xss = require('xss-clean');
const cookieParser = require('cookie-parser');
const express = require('express');
// DataBase and Middlewares
const connectDB = require('./db/connect.js');
const {
rateLimiterUsingThirdParty,
} = require('./middlewares/rateLimiter.js');
// Routes
const authRoutes = require('./routes/auth.routes.js');
const userRoutes = require('./routes/user.routes.js');
const restRoutes = require('./routes/restaurant.routes.js');
// error handler
const notFoundMiddleware = require('./middlewares/not-found');
const errorHandlerMiddleware = require('./middlewares/error-handler');
const app = express();
// Middlewares
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(
cors({
origin: '*',
})
);
app.set('trust proxy', 1);
app.use(helmet());
app.use(xss());
app.use(cookieParser());
// API-DOCUMENTATION
app.get('/', (req, res) => {
res.send('<h1>Restaurants API</h1>');
});
// routes
app.use('/api/v1/auth', rateLimiterUsingThirdParty, authRoutes);
app.use('/api/v1/users', userRoutes);
app.use('/api/v1/restaurants', restRoutes);
app.use(notFoundMiddleware);
app.use(errorHandlerMiddleware);
const port = process.env.PORT || 5000;
const start = async () => {
try {
connectDB(process.env.MONGO_URI);
app.listen(port, () =>
console.log(`Server is listening on port ${port}...`)
);
} catch (error) {
console.log(error);
}
};
start();
module.exports = app;
hope you are good,
I am building my next.js weather app project using openweather API, I set up my proxy server, so the API key won't appear on the client side, it works perfect on my localhost, but when I deploy it on vercel or heroku, it returns error 404, it does the same when requesting directly on postman or browser.
PS: the environment variables are set in my vercel dashboard.
PS: api url example localhost:3000/api/weather?q=london
my server.js
const next = require('next');
const port = parseInt(process.env.PORT, 10) || 3000;
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();
const needle = require('needle');
const url = require('url');
const cors = require('cors');
app.prepare().then(() => {
const API_BASE_URL = process.env.API_BASE_URL;
const API_KEY_NAME = process.env.API_KEY_NAME;
const API_KEY_VALUE = process.env.API_KEY_VALUE;
const server = express();
server.use(
cors({
origin: '*',
})
);
server.get(
'/api/:stat',
async (req, res) => {
try {
const params = new URLSearchParams({
...url.parse(req.url, true).slashes,
...url.parse(req.url, true).query,
[API_KEY_NAME]: API_KEY_VALUE,
});
const apiRes = await needle(
'get',
`${API_BASE_URL}/${req.params.stat}?${params}`
);
const data = apiRes.body;
res.status(200).json(data);
} catch (error) {
res.status(500).json({ error });
}
}
);
server.all('*', (req, res) => {
return handle(req, res);
});
server.listen(port, (err) => {
if (err) throw err;
console.log(`> Ready on http://localhost:${port}`);
});
});
Working on a MERN application as a way to learn how it all works, but I am stuck trying to get my routes to display. I don't get any other errors, and if I use a simple app.get('/'), I am able to see that just fine; it seems that the routes I have defined are not being recognized for some reason.
require('dotenv').config();
const express = require('express');
const cors = require('cors');
const app = express();
const port = process.env.PORT;
const options = {
origin: 'http://localhost:8081'
}
app.use(cors(options));
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
const db = require('./models');
db.mongoose
.connect(db.url, {
useNewUrlParser: true,
useUnifiedTopology: true,
})
.then(() => {
console.log('Successfully connected.');
})
.catch((error) =>{
console.log(`Connection failed. Error: ${error}`);
process.exit();
}
);
require('./routes/items.routes')(app)
app.listen(port, () => {
console.log(`Listening at localhost:${port}`);
});
const multer = require('multer');
const dir = './public/';
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, dir);
},
filename: (req, file, cb) => {
const fileName = file.originalname.toLowerCase().split(' ').join('-');
cb(null, fileName + '-' + Date.now());
}
});
var upload = multer({
storage: storage,
fileFilter: (req, file, cb) => {
if (file.mimetype == 'image/png' || file.mimetype == 'image/jpg' || file.mimetype == 'image/jpeg') {
cb(null, true);
} else {
cb(null, false);
return cb(new Error('Invalid file type.'));
}
}
});
module.exports = app => {
const items = require('../controllers/items.controller');
let router = require('express').Router();
router.post('/', upload.single('icon'), items.create);
router.delete('/:id', items.delete);
app.use('/api/items', router);
};
I followed this and this as a start point. Unsure what I am missing or why it is unable to retrieve my POST route.
The error in your title:
Cannot GET /api/items
means it is a GET request to /api/items. But, you don't have a GET handler for that route. You only have a POST handler for that route defined with these two lines of code:
router.post('/', upload.single('icon'), items.create);
app.use('/api/items', router);
So, you apparently need to change your test on that route to a POST, not a GET and the POST will be expecting a body part with the data for an icon in it.
If you want to see exactly what is getting to your router (for debugging/troubleshooting purposes), you can add this right after you declare the router as the first item you register on the router.
router.use((req, res, next) => {
console.log(`In router: ${req.method}:${req.originalUrl}`);
next();
});
I am new to express and next and was trying to set 'localhost:3000/newpage' and 'localhost:3000/newpage/' as the same route however as I add a '/' at the end it shows a 404 error.
I am using "next-routes" for dynamic routing and have created routes.js file that looks like this:
const nextRoutes = require("next-routes");
const routes = (module.exports = nextRoutes());
routes.add("index", "/");
routes.add("newpage", "/newpage/:slug"); //with body parser this doesnt work
and my server.js file looks like this:
const express = require("express");
const next = require("next");
const routes = require("./routes");
const dev = process.env.NODE_ENV !== "production";
const port = process.env.PORT || 3000;
const app = next({ dev });
const handle = app.getRequestHandler();
const bodyParser = require("body-parser");
const handler = routes.getRequestHandler(app);
app
.prepare()
.then(() => {
const server = express();
server.use(bodyParser.json()); //with this dynamic routes dont work
server.use (handler); //with this dynamic routes work but / url show 404
server.get("*", (req, res) => {
server.use(handler);
if (req.url.endsWith("/")) {
req.url = req.url.slice(0, -1); // works only when using body parser
}
return handle(req, res);
});
server.listen(port, (err) => {
if (err) throw err;
console.log("> Ready on http://localhost:3000");
});
})
.catch((ex) => {
console.error(ex.stack);
process.exit(1);
});
You can modify the url that you get before passing it to Next's handling.
const next = require('next');
const express = require('express');
const routes = require('./routes');
const port = process.env.PORT || 3000;
const dev = process.env.NODE_ENV !== 'production';
const app = next({dev});
const handle = app.getRequestHandler();
// const handler = routes.getRequestHandler(app); // redundant line
app.prepare().then(() => {
const server = express();
// server.use(handler); // <-- this line is redundant since you need only one handle!
server.get('*', (req, res) => {
if (req.url.endsWith('/')) {
req.url = req.url.slice(0, -1); // remove the last slash
}
return handle(req, res);
});
server.listen(port, (err) => {
if (err) throw err;
console.log('> Ready on http://localhost:3000');
});
});
Working example: https://codesandbox.io/s/express-nextjs-react-c47y8?file=/src/index.js
Navigate to /form or /form/
I had to install the body-parser package then used body-parser. I also changed the folder structure such that I didn't have to import the routes. The final code in server.js looks like this:
const express = require("express");
const next = require("next");
const dev = process.env.NODE_ENV !== "production";
const port = process.env.PORT || 3000;
const app = next({ dev });
const handle = app.getRequestHandler();
app
.prepare()
.then(() => {
const server = express();
server.get("*", (req, res) => {
if (req.url.endsWith("/")) {
req.url = req.url.slice(0, -1); // remove the last slash
}
return handle(req, res);
});
server.listen(port, (err) => {
if (err) throw err;
console.log("> Ready on http://localhost:3000");
});
})
.catch((ex) => {
console.error(ex.stack);
process.exit(1);
});
I am working on a Node API that I can use to run some commands on the Terminal.
For example, when I go to: http://localhost:3000/runLS the command ls -la is run on my working directory and the output is given back to the API as a JSON.
I have gotten as far as being able to run the terminal command from the API.
I have two code files:
commands.js which is where I have defined my commands.
var exec = require('child_process').exec;
function puts(error, stdout, stderr) {
console.log(stdout)
}
const runLS = (request, response) => {
exec("ls -la", puts, (error, results) => {
if(error) {
throw error
}
})
}
module.exports = {
runLS
}
I also have app.js:
const express = require('express')
const cors = require('cors')
const app = express()
const port = 3000
var corsOptions = {
origin: '*',
credentials: true };
app.use(cors(corsOptions));
app.get('/', (request, response) => {
response.json({ info: 'Commandline status API ' })
})
const comm = require('./commands_test.js')
app.get('/runLS', comm.runLS)
app.listen(port, () => {
console.log(`App running on port ${port}.`)
})
When I run this and then go to http://localhost:3000/runLS I get the stdout on the terminal. I, however, want it to appear on the browser as a JSON.
I edited my command.js file as below:
var exec = require('child_process').exec;
const runLS = (error, stdout, stderr) => {
exec("ls -la", (error, results) => {
if(error) {
throw error
}
stdout.status(200).json(stdout.rows)
})
}
module.exports = {
runLS
}
and then edited my app.js:
const express = require('express')
const bodyParser = require('body-parser')
const cors = require('cors')
const app = express()
const port = 3000
var corsOptions = {
origin: '*',
credentials: true };
app.use(cors(corsOptions));
app.use(bodyParser.json())
app.use(
bodyParser.urlencoded({
extended: true,
})
)
app.get('/', (request, response) => {
response.json({ info: 'Commandline status API ' })
})
const comm = require('./commands_test.js')
app.get('/runLS', comm.runLS)
app.listen(port, () => {
console.log(`App running on port ${port}.`)
})
When I go to the endpoin now am just getting nothing, there are no errors on the terminal either. I am a Node noob so I would appreciate explanations in simple language.
Any ideas?
[If it means anything, I am working on Git Bash on windows as my terminal]
stdout.rows does not exist because it's an express response object.
var exec = require('child_process').exec;
const runLS = (req, res, next) => {
exec("ls -la", (error, results) => {
if (error) {
res.status(400).send(error);
}
res.status(200).json({
results: results
})
})
}
module.exports = {
runLS
}