url:
https://pedantic-hermann-961116.netlify.app/
When deploying my express/mongoDB app to Netlify I keep running into a 404 error when hitting my endpoint. When testing the post request locally (http://localhost:5000/.netlify/functions/api/shorten) and
{
"longUrl": "https://www.katalon.com/resources-center/blog/ci-cd-tools/"
}
in the body. I am getting the correct response back:
{
"_id":"60e6026e67a0b24e5fd228bc",
"longUrl":"https://www.katalon.com/resources-center/blog/ci-cd-tools/",
"shortUrl":"http://localhost:5000/U-MwiSyGa",
"urlCode":"U-MwiSyGa",
"date":"Wed Jul 07 2021 15:37:18 GMT-0400 (Eastern Daylight Time)",
"__v":0
}
When I preview the function in the dashboard it is running.
However if I open up the endpoint in a browser. I get the error below.
{"errorType":"Error","errorMessage":"Configuration property \"mongoURI\" is not defined","trace":["Error: Configuration property \"mongoURI\" is not defined"," at w.get (/var/task/index.js:1624:1824)"," at Object.<anonymous> (/var/task/index.js:1783:1669)"," at n (/var/task/index.js:1:158)"," at Object.<anonymous> (/var/task/index.js:1624:13555)"," at n (/var/task/index.js:1:158)"," at /var/task/index.js:1:957"," at Object.<anonymous> (/var/task/index.js:1:968)"," at Module._compile (internal/modules/cjs/loader.js:999:30)"," at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)"," at Module.load (internal/modules/cjs/loader.js:863:32)"," at Function.Module._load (internal/modules/cjs/loader.js:708:14)"," at Module.require (internal/modules/cjs/loader.js:887:19)"," at require (internal/modules/cjs/helpers.js:74:18)"," at _tryRequire (/var/runtime/UserFunction.js:75:12)"," at _loadUserApp (/var/runtime/UserFunction.js:95:12)"," at Object.module.exports.load (/var/runtime/UserFunction.js:140:17)"]}
config/db.js
const mongoose = require('mongoose');
const config = require('config');
const db = config.get('mongoURI');
const connectDB = async () => {
try {
await mongoose.connect(db, {
useNewUrlParser: true
});
console.log('MongoDB Connected...');
} catch (err) {
console.error(err.message);
process.exit(1);
}
};
module.exports = connectDB;
config/default.json
{
"mongoURI": "mongodb+srv://user:password@cluster0.eqzr789.mongodb.net/myFirstDatabase?retryWrites=true&w=majority",
"baseUrl": "https://pedantic-hermann-961116.netlify.app/"
}
dist/
empty index.html
models/Url.js
const mongoose = require('mongoose');
const urlSchema = new mongoose.Schema({
urlCode: String,
longUrl: String,
shortUrl: String,
date: { type: String, default: Date.now }
});
module.exports = mongoose.model('Url', urlSchema);
routes/index.js
const express = require('express');
const router = express.Router();
const Url = require('../models/Url');
// @route GET /:code
// @desc Redirect to long/original URL
router.get('/:code', async (req, res) => {
try {
const url = await Url.findOne({ urlCode: req.params.code });
if (url) {
return res.redirect(url.longUrl);
} else {
return res.status(404).json('No url found');
}
} catch (err) {
console.error(err);
res.status(500).json('Server error');
}
});
module.exports = router;
routes/url.js
const express = require('express');
const router = express.Router();
const validUrl = require('valid-url');
const shortid = require('shortid');
const config = require('config');
const Url = require('../models/Url');
// @route POST /api/url/shorten
// @desc Create short URL
router.post('/shorten', async (req, res) => {
const { longUrl } = req.body;
const baseUrl = config.get('baseUrl');
// Check base url
if (!validUrl.isUri(baseUrl)) {
return res.status(401).json('Invalid base url');
}
// Create url code
const urlCode = shortid.generate();
// Check long url
if (validUrl.isUri(longUrl)) {
try {
let url = await Url.findOne({ longUrl });
if (url) {
res.json(url);
} else {
const shortUrl = baseUrl + '/' + urlCode;
url = new Url({
longUrl,
shortUrl,
urlCode,
date: new Date()
});
await url.save();
res.json(url);
}
} catch (err) {
console.error(err);
res.status(500).json('Server error');
}
} else {
res.status(401).json('Invalid long url');
}
});
module.exports = router;
src/index.js
const express = require('express');
const connectDB = require('../config/db');
const serverless = require("serverless-http");
const app = express();
// Connect to database
connectDB();
app.use(express.json());
// Define Routes
app.use('/', require('../routes/index'));
app.use('/.netlify/functions/api', require('../routes/url'));
const PORT = 5000;
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
module.exports = app;
module.exports.handler = serverless(app);
package.json
{
"name": "url_shortner_service",
"version": "1.0.0",
"description": "",
"main": "src/index.js",
"scripts": {
"start": "node src/index",
"dev": "nodemon src/index",
"build": "NODE_ENV=production ./node_modules/.bin/netlify-lambda build src"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"config": "^3.1.0",
"express": "^4.17.1",
"mongodb-client-encryption": "^1.2.6",
"mongoose": "^5.6.4",
"netlify-lambda": "^2.0.11",
"serverless-http": "^2.7.0",
"shortid": "^2.2.14",
"valid-url": "^1.0.9"
},
"devDependencies": {
"nodemon": "^1.19.1"
}
}
netlify.toml
[build]
functions = "functions"
[dev]
publish = "dist"