MERN-Stack Heroku - Cannot GET / - github

Trying to get a MERN-Stack to Deploy on Heroku I've added MONGOBD_URI as a key in Config Vars on Heroku and added the MongoDB Atlas value.
Heroku is connected directly to the Github repo and not through the Heroku CLI. I have it set to auto-deploy but recently redeployed it manually.
This was the Heroku Build Log:
-----> Node.js app detected
-----> Creating runtime environment
NPM_CONFIG_LOGLEVEL=error
NODE_VERBOSE=false
NODE_ENV=production
NODE_MODULES_CACHE=true
-----> Installing binaries
engines.node (package.json): unspecified
engines.npm (package.json): unspecified (use default)
Resolving node version 12.x...
Downloading and installing node 12.20.0...
Using default npm version: 6.14.8
-----> Restoring cache
Cached directories were not restored due to a change in version of node, npm, yarn or stack
Module installation may take longer for this build
-----> Installing dependencies
Installing node modules
> nodemon#2.0.6 postinstall /tmp/build_b41198ca_/node_modules/nodemon
> node bin/postinstall || exit 0
Love nodemon? You can now support the project via the open collective:
> https://opencollective.com/nodemon/donate
added 290 packages in 6.983s
-----> Build
-----> Caching build
- node_modules
-----> Pruning devDependencies
removed 1 package and audited 289 packages in 2.051s
17 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
-----> Build succeeded!
-----> Discovering process types
Procfile declares types -> (none)
Default types for buildpack -> web
-----> Compressing...
Done: 33M
-----> Launching...
Released v17
https://jms-r0b.herokuapp.com/ deployed to Heroku
The browser(Chrome) only renders Cannot GET / and consol.log()'s GET https://jms-r0b.herokuapp.com/ 404 (Not Found) jms-r0b.herokuapp.com/:1
This is the LINK to my repo.
Here's how my server.js is setup:
const express = require("express");
const app = express();
const bodyParser = require("body-parser");
const cors = require("cors");
const mongoose = require("mongoose");
const todoRoutes = express.Router();
const PORT = process.env.PORT || 4000;
let Todo = require("./models/todo.model");
app.use(cors());
app.use(bodyParser.json());
// Express data parsing
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(express.static("public"));
const URI = process.env.MONGODB_URI || "mongodb://localhost/todos";
mongoose.connect(
URI,
{
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true,
useFindAndModify: false,
},
(err) => console.log(err)
);
const connection = mongoose.connection;
connection.once("open", () => {
console.log("MongoDB database connection established successfully");
});
todoRoutes.route("/").get((req, res) => {
Todo.find((err, todos) => {
if (err) {
console.log(err);
} else {
res.json(todos);
}
});
});
todoRoutes.route("/:id").get((req, res) => {
let id = req.params.id;
Todo.findById(id, (err, todo) => {
res.json(todo);
});
});
todoRoutes.route("/update/:id").post((req, res) => {
Todo.findById(req.params.id, (err, todo) => {
if (!todo) {
res.status(404).send("data is not found");
} else {
todo.todo_description = req.body.todo_description;
todo.todo_responsible = req.body.todo_responsible;
todo.todo_priority = req.body.todo_priority;
todo.todo_completed = req.body.todo_completed;
todo
.save()
.then((todo) => {
res.json("Todo updated!");
})
.catch((err) => {
res.status(400).send("Update not possible");
});
}
});
});
todoRoutes.route("/add").post((req, res) => {
let todo = new Todo(req.body);
todo
.save()
.then((todo) => {
res.status(200).json({ todo: "todo added successfully" });
})
.catch((err) => {
res.status(400).send("adding new todo failed");
});
});
todoRoutes.route("/delete/:id").delete((req, res) => {
Todo.findByIdAndRemove(req.params.id, (err, todo) => {
if (!todo) {
res.status(404).send("data is not found");
} else {
res.status(200).json({
msg: todo,
});
}
});
});
app.use("/todos", todoRoutes);
app.listen(PORT, () => {
console.log("http://localhost:" + PORT);
console.log(".env.PORT:" + process.env.PORT);
});
and this is how my root package.json looks:
{
"name": "rob",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"start:dev": "cd client && npm start",
"client": "cd client && npm run start",
"start": "concurrently \"node server/server.js\" \"npm run client\"",
"dev": "concurrently \"nodemon server/server.js\" \"npm run client\""
},
"repository": {
"type": "git",
"url": "git+https://github.com/WasteOfADrumBum/r0b.git"
},
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/WasteOfADrumBum/r0b/issues"
},
"homepage": "https://github.com/WasteOfADrumBum/r0b#readme",
"dependencies": {
"bcryptjs": "^2.4.3",
"concurrently": "^5.3.0",
"cors": "^2.8.5",
"express": "^4.17.1",
"express-mongo-sanitize": "^2.0.0",
"express-rate-limit": "^5.1.3",
"helmet": "^4.2.0",
"hpp": "^0.2.3",
"ini": "^2.0.0",
"mongoose": "^5.10.13",
"nodemon": "^2.0.6",
"react": "^17.0.1",
"react-cool-onclickoutside": "^1.5.8",
"react-dom": "^17.0.1",
"validator": "^12.0.0",
"xss-clean": "^0.1.1"
},
"devDependencies": {
"dotenv": "^8.2.0"
}
}
I could use a little help. I've deployed 5 other MERN-Stacks with a MongoDB Atlas or JawsDB connection with little to no issues and this one is just throwing me for a loop.
PLEASE HELP!!!

Everyone does things differently, but I think the error is in your connection to MongDB- are you establishing a connection OK or no?
If no connection - You said "I've added MONGOBD_URI as a key in Config Vars on Heroku and added the MongoDB Atlas value." But I see that "config Vars" is not used in your code- you used the .env as you should to keep your connection password secure...so may just need to add your connection URI to the .env file, and you are good to go?
If your connection is fine, then I would look to your server and suggest to test if the problem is solved using the standard routing:
app.route("/")
.get(function(req, res) {
res.sendFile(process.cwd() + "/views/index.html");
})

Related

MERN Stack Error: how to resolve "Cannot GET /" error when running backend server?

I know there are loads of posts on stack overflow about this issue. However, I can't find the solution to this problem when I try what is suggested on the other posts and some answers I don't find them very clear. That's why, I thought it useful to ask this question by emphasizing where my mistake is. So I am currently working on the backend of my MERN application, when I run my server I get the following message in my terminal .Personally I am a beginner and I was expecting it to tell me that everything went successfully and it automatically opens a tab for me on my browser. When I manually open the tab at the specified address i.e.: http://localhost:5000/, I get the error Cannot GET / I don't even know what it means. Here are the contents of my files:
config.js
module.exports = {
PORT: process.env.PORT || 4000,
MONGODB_URI: process.env.MONGODB_URI || "mongodb://localhost:27017/facebook_clone",
JWT_SECRET: process.env.JWT_SECRET || "itssecret",
JWT_EXP: process.env.JWT_EXPIRE || '10h',
ADMIN_EMAIL: process.env.ADMIN_EMAIL || "admin#gmail.com",
ADMIN_PASSWORD: process.env.ADMIN_PASSWORD || "admin#123",
}
index.js
const express = require('express')
const cors = require('cors')
const mongoose = require('mongoose')
require("dotenv").config()
const app = express()
const http = require('http')
const server = http.createServer(app)
const io = require('socket.io')(server)
const UserRoutes = require('./routes/User')
const AuthRoutes = require('./routes/Auth')
const PostRoutes = require('./routes/Post')
const PORT = process.env.PORT || 5000
const {MONGODB_URI} = require("./config")
app.use(cors())
app.use(express.json())
app.use((req, res, next) => {
io.req = req
req.io = io
next()
})
app.use('/api/auth', AuthRoutes)
app.use('/api/user', UserRoutes)
app.use('/api/post', PostRoutes)
require('./socket')(io)
mongoose
.connect(MONGODB_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true,
})
.then(() => {
console.log('database connected')
server.listen(PORT, () => console.log(`server started on port ${PORT}`))
})
.catch((err) => console.log(err))
package.json
{
"name": "server",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"scripts": {
"dev": "nodemon index.js",
"start": "node index.js"
},
"dependencies": {
"bcrypt": "^5.0.0",
"cors": "^2.8.5",
"dotenv": "^8.2.0",
"express": "^4.18.1",
"heroku": "^7.60.2",
"jsonwebtoken": "^8.5.1",
"mongodb": "^3.7.3",
"mongoose": "^5.10.7",
"multer": "^1.4.2",
"socket.io": "^2.4.1"
},
"devDependencies": {
"nodemon": "^2.0.4"
}
}
I even tried to change the port number from 4000 to 5000 in my config.js file but without success. And so I hope more experienced members of the community can help me. Thanks a lot !
probably the reason is that you did not specify that route in your app in your routes for example app.use("/"), otherwise in your browser URL if you navigate to one of the routes below you'll get a result:
HTTP://localhost:5000/api/auth
HTTP://localhost:5000/api/user
HTTP://localhost:5000/api/post

After successfully deploying Next.js app on AWS Amplify, https://www.example.com/api/any-route showing below error in console

The app is deployed successfully but the API routes (/pages/api) are not working as expected, showing below error in the console.
Build is successful and deployed on aws-amplify, I have added environment variables correctly, don't know why this is happening?
Does aws-amplify doesn't support serverless functions writer inside /api folder??
{
"error": {
"message": "connect ECONNREFUSED 127.0.0.1:80",
"name": "Error",
"stack": "Error: connect ECONNREFUSED 127.0.0.1:80\n at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1148:16)",
"config": {
"url": "undefined/campaigns",
"method": "get",
"headers": {
"Accept": "application/json, text/plain, */*",
"User-Agent": "axios/0.21.4"
},
"auth": {},
"transformRequest": [null],
"transformResponse": [null],
"timeout": 0,
"xsrfCookieName": "XSRF-TOKEN",
"xsrfHeaderName": "X-XSRF-TOKEN",
"maxContentLength": -1,
"maxBodyLength": -1,
"transitional": {
"silentJSONParsing": true,
"forcedJSONParsing": true,
"clarifyTimeoutError": false
}
},
"code": "ECONNREFUSED"
}
}
Here is the code
import axios from 'axios';
import Cors from 'cors';
import rateLimit from '../../../utils/rate-limit';
import initMiddleware from '../../../lib/init-middleware';
// Initialize the cors middleware
const cors = initMiddleware(
Cors({
methods: ['POST'],
origin: ['https://www.example.com', /\.example\.com$/],
})
);
const limiter = rateLimit({
interval: 60 * 1000, // 60 seconds
uniqueTokenPerInterval: 500, // Max 500 users per second
});
const handler = async (req, res) => {
await cors(req, res);
if (req.method === 'GET') {
try {
await limiter.check(res, 50, 'CACHE_TOKEN');
const { data } = await axios.get(`${process.env.BASE_URL}/campaigns`, {
auth: {
username: process.env.MAIL_SERVER_USERNAME,
password: process.env.MAIL_SERVER_PASSWORD,
},
});
return res.status(200).json(data);
} catch (error) {
return res.status(429).json({ error });
}
} else {
try {
await limiter.check(res, 10, 'CACHE_TOKEN'); // 10 requests per minute
return res.status(200).json('not allowed');
} catch (err) {
return res.status(429).json({ error: 'Rate limit exceeded' });
}
}
};
export default handler;
I figured out that environment variables are not getting reflected, so did some googling; found this solution and it worked for me.
Add your desired environment variable in the Amplify Console-like normal (steps)
Update (or create) your next.config.js file with the environment variable you added in the Amplify Console. E.g if you created an environment variable named MY_ENV_VAR in the console in step 1) above, then you would add the following:
module.exports = {
env: {
MY_ENV_VAR: process.env.MY_ENV_VAR
}
};
Now after your next build you will be able to reference your environment variable (process.env.MY_ENV_VAR) in your SSR lambdas!
Here is the link: Github
Ran into the same problem Amplify only supports NextJS 11 at the moment. If you go with the default settings it will use the latest NextJS 12 and /api routes wont work, they return a 503 with a cloudformation permission error.
Specify next 11.1.3 in your package.json
https://aws.amazon.com/about-aws/whats-new/2021/08/aws-amplify-hosting-support-next-js-version-11/
I also faced that problem. Amplify does not support v12 of next. Simply downgrade your next.js version in package.json to v1.1.3 and your routes will work as normal.
Best regrets.
Artem Meshkov

Cannot test a native Android app using codeceptJS

I have created a codeceptJS project by following the mobile testing setup steps located here: https://codecept.io/mobile/#setting-up
So far, I'm unable to test any apps via simulator; I instead get the following error:
1) login
I should be able to login with the correct username and password:
>> The requested resource could not be found, or a request was received using an HTTP method that is not supported by the mapped resource <<
at Object.getErrorFromResponseBody (node_modules/webdriver/build/utils.js:189:12)
at NodeJSRequest._request (node_modules/webdriver/build/request/index.js:157:31)
at processTicksAndRejections (internal/process/task_queues.js:93:5)
I have verified my appium config using appium-doctor, and there are no issues found.
My codecept.conf.js is as follows:
const path = require('path');
const { setHeadlessWhen } = require('#codeceptjs/configure');
// turn on headless mode when running with HEADLESS=true environment variable
// export HEADLESS=true && npx codeceptjs run
setHeadlessWhen(process.env.HEADLESS);
exports.config = {
tests: './*_test.js',
output: './output',
helpers: {
Appium: {
platform: 'Android',
device: 'emulator',
desiredCapabilities: {
avd: 'Pixel_5_API_28',
app: path.resolve('./sample_apps/Android.apk'),
appActivity: 'com.swaglabsmobileapp.MainActivity'
}
},
},
include: {
I: './steps_file.js'
},
bootstrap: null,
mocha: {},
name: 'appium-codecept-android-POC',
plugins: {
pauseOnFail: {},
retryFailedStep: {
enabled: true
},
tryTo: {
enabled: true
},
screenshotOnFail: {
enabled: true
}
}
}
And here's my package.json as created by codeceptjs init:
{
"name": "appium-codecept-android-POC",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"codeceptjs": "^3.0.7",
"webdriverio": "^7.9.0"
}
}
Finally, my test file is as follows:
Feature('login');
Scenario('I should be able to login with the correct username and password', ({ I }) => {
setTimeout(() => {
I.see('Username');
}, 3000);
I.click('//android.widget.EditText[#content-desc="test-Username"]');
I.fillField('//android.widget.EditText[#content-desc="test-Username"]', 'standard_user');
I.click('//android.widget.EditText[#content-desc="test-Password"]');
I.fillField('//android.widget.EditText[#content-desc="test-Password"]', 'secret_sauce');
I.click('//android.view.ViewGroup[#content-desc="test-LOGIN"]');
I.waitForElement('//android.view.ViewGroup[#content-desc="test-Cart drop zone"]/android.view.ViewGroup/android.widget.TextView', 3)
I.dontSeeElement('//android.view.ViewGroup[#content-desc="test-Error message"]/android.widget.TextView');
});
Scenario('I should not be able to login with an incorrect username or password', ({ I }) => {
setTimeout(() => {
I.see('Username');
}, 3000);
I.click('//android.widget.EditText[#content-desc="test-Username"]');
I.fillField('//android.widget.EditText[#content-desc="test-Username"]', 'bob');
I.click('//android.widget.EditText[#content-desc="test-Password"]');
I.fillField('//android.widget.EditText[#content-desc="test-Password"]', 'secret_sauce');
I.click('//android.view.ViewGroup[#content-desc="test-LOGIN"]');
I.waitForElement('//android.view.ViewGroup[#content-desc="test-Cart drop zone"]/android.view.ViewGroup/android.widget.TextView', 3)
I.dontSeeElement('//android.view.ViewGroup[#content-desc="test-Error message"]/android.widget.TextView');
});
Scenario('I should be able to see details', ({ I }) => {
// login
setTimeout(() => {
I.see('Username');
}, 3000);
I.click('//android.widget.EditText[#content-desc="test-Username"]');
I.fillField('//android.widget.EditText[#content-desc="test-Username"]', 'standard_user');
I.click('//android.widget.EditText[#content-desc="test-Password"]');
I.fillField('//android.widget.EditText[#content-desc="test-Password"]', 'secret_sauce');
I.click('//android.view.ViewGroup[#content-desc="test-LOGIN"]');
I.waitForElement('//android.view.ViewGroup[#content-desc="test-Cart drop zone"]/android.view.ViewGroup/android.widget.TextView', 3)
// should be able to click a label to see details
I.click('(//android.widget.TextView[#content-desc="test-Item title"])[2]');
I.seeElement('//android.view.ViewGroup[#content-desc="test-Description"]/android.widget.TextView[2]');
I.click('//android.view.ViewGroup[#content-desc="test-BACK TO PRODUCTS"]');
});
I'm at a loss here, as I haven't done anything except follow the setup instructions. Executing against ios works; it is only the android execution that fails. Appium is installed and running, env vars are set, etc. Any help would be appreciated, as this could be a deal breaker for me in terms of whether or not I can use codeceptjs. I love the project and really want to use it, but I must be able to test both ios and android native apps.
One final note: If anyone wants to try this config, the app I am using for the above test can be found here: https://github.com/saucelabs/sample-app-mobile/releases/download/2.7.1/Android.SauceLabs.Mobile.Sample.app.2.7.1.apk

Error- Warning, FIREBASE_CONFIG environment variable is missing. Initializing firebase-admin will fail

I tried to connect my existing firestore database to Dialogflow fulfillment. The function deployed to Google CLoud Function successfully but I cannot add data to my database. I have tried to change the node version 8 but still failed. Please help me.
Index.js
'use strict';
const admin = require('firebase-admin');
const {WebhookClient} = require('dialogflow-fulfillment');
const {Card, Suggestion} = require('dialogflow-fulfillment');
admin.initializeApp({
apiKey: "Axxxx",
authDomain: "/xxxxx.firebaseio.com",
databaseURL: "https:/xxxxxx.firebaseio.com",
projectId: "mxxxxx8",
storageBucket: "xxxxx.com",
});
const functions = require('firebase-functions');
const settings = {timestampsInSnapshots: true};
var db = admin.firestore();
admin.firestore().settings({ timestampsInSnapshots: true });
process.env.DEBUG = 'dialogflow:debug'; // enables lib debugging statements
exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
const agent = new WebhookClient({ request, response });
console.log('Dialogflow Request headers: ' + JSON.stringify(request.headers));
console.log('Dialogflow Request body: ' + JSON.stringify(request.body));
function welcome(agent) {
agent.add(`Welcome to my agent!`);
}
function fallback(agent) {
agent.add(`I didn't understand`);
agent.add(`I'm sorry, can you try again?`);
}
// Run the proper function handler based on the matched Dialogflow intent name
let intentMap = new Map();
intentMap.set('Default Welcome Intent', welcome);
intentMap.set('Default Fallback Intent', fallback);
// intentMap.set('your intent name here', yourFunctionHandler);
// intentMap.set('your intent name here', googleAssistantHandler);
agent.handleRequest(intentMap);
});
package.json
{
"name": "dialogflowFirebaseFulfillment",
"description": "This is the default fulfillment for a Dialogflow agents using Cloud Functions for Firebase",
"version": "0.0.1",
"private": true,
"license": "Apache Version 2.0",
"author": "Google Inc.",
"engines": {
"node": "8"
},
"scripts": {
"start": "firebase serve --only functions:dialogflowFirebaseFulfillment",
"deploy": "firebase deploy --only functions:dialogflowFirebaseFulfillment"
},
"dependencies": {
"actions-on-google": "^2.2.0",
"firebase-admin": "~7.1.1",
"firebase-functions": "^2.2.1",
"dialogflow": "^0.6.0",
"dialogflow-fulfillment": "^0.5.0"
}
The solution is upgrade your Firebase project plan to Blaze Plan. Then make a new Dialogflow agent under that Firebase project.
Your Firebase initialization seems wrong. Here's how you should do it:
.
.
.
admin.initializeApp({
credential: admin.credential.applicationDefault(),
databaseURL: 'https://<DATABASE_NAME>.firebaseio.com'
});
.
.
.
This should work.
Based on the documentation it should be like this,
serviceAccount = require('./serviceAccount.json');
const adminConfig = JSON.parse(process.env.FIREBASE_CONFIG);
adminConfig.credential = admin.credential.cert(serviceAccount);
admin.initializeApp(adminConfig);

Protractor browserstack-local config stopped working and throws generic error

I was able to run my Protractor tests using browserstack-local earlier tonight but was unable to by the end of the evening and I can't figure out what's going on.
node v7.4.0
protractor v5.0.0
browserstack-local v1.2.0
Here's my conf.ts file:
'use strict';
import { Config, browser } from 'protractor';
import testSuites = require('./testSuites.js');
import browserstack = require('browserstack-local');
const commonCapabilities = {
'browserstack.user': '*****',
'browserstack.key': '*****',
'browserstack.local': true
};
export let config: Config = {
baseUrl: 'https://localhost:8443',
seleniumAddress: 'http://hub-cloud.browserstack.com/wd/hub',
multiCapabilities: [{
browserName: 'chrome',
browser_version: '54.0',
os: 'Windows',
os_version: '10',
resolution: '1280x800'
}],
specs: ['src/**/*spec.js'],
suites: testSuites.suites,
framework: 'mocha',
mochaOpts: {
reporter: 'spec',
slow: 0,
timeout: 60000
},
allScriptsTimeout: 3600000,
onPrepare: () => {
browser.manage().window().setSize(1280, 800);
},
params: {
user: 'seleniumtesting'
},
beforeLaunch() {
console.log('Starting BrowserStack Local...');
return new Promise((resolve, reject) => {
exports.bs_local = new browserstack.Local();
exports.bs_local.start({ key: commonCapabilities['browserstack.key']}, error => {
if (error) {
return reject(error);
}
console.log('BrowserStack Started.');
resolve();
});
});
},
afterLaunch() {
return new Promise(resolve => {
if (!exports.bs_local) {
console.log('Skipping shutdown of BrowserStack Local...');
resolve();
return;
}
console.log('Stopping BrowserStack Local...');
exports.bs_local.stop(resolve);
});
}
};
// Code to support common capabilities
exports.config.multiCapabilities.forEach((caps) => {
Object.keys(commonCapabilities).forEach(i => {
caps[i] = caps[i] || commonCapabilities[i];
});
});
When I run my Protractor tests I'm getting:
Starting BrowserStack Local...
(node:3755) DeprecationWarning: os.tmpDir() is deprecated. Use os.tmpdir() instead.
/usr/local/lib/node_modules/protractor/node_modules/q/q.js:155
throw e;
^
Error
at /protractor/node_modules/browserstack-local/lib/Local.js:57:20
at ChildProcess.exithandler (child_process.js:202:7)
at emitTwo (events.js:106:13)
at ChildProcess.emit (events.js:191:7)
at maybeClose (internal/child_process.js:885:16)
at Socket.<anonymous> (internal/child_process.js:334:11)
at emitOne (events.js:96:13)
at Socket.emit (events.js:188:7)
at Pipe._handle.close [as _onclose] (net.js:501:12)
It's strange because I didn't change anything in my environment since it was last working earlier in the evening, and now I can't get it to run anymore without seeing this error. I've been trying to debug this without any luck, could someone please help me spot if I'm missing anything?
Thanks in advance!
"os.tmpDir" deprecated onwards Node v7.0.0. Try downgrading your Node and execute.
More details are available in https://github.com/hapijs/hapi/issues/3369