I am getting the above error message in my Postman while setting up a new POST request using my heroku url as initial and current values in Globals.
Postman returns 'Route does not exist' and when I check the Postman console I get "JSONError: Unexpected token 'R' at 1:1 Route does not exist ^"
Postman worked fine up until now I am trying to use heroku with it. The POST request still works fine while the url is local://host/api/v1 ... however with heroku url is gives back that error message.
I don't know what I am doing wrong and I have been stuck since last week, help will be appreciated. Thank you
THIS IS MY app.js CODE
require('dotenv').config();
require('express-async-errors');
//extra security packages
const helmet = require('helmet')
const cors = require('cors')
const xss = require('xss-clean')
const rateLimiter = require('express-rate-limit')
const express = require('express');
const app = express();
//connecting dB
const connectDB = require('./db/connect')
const authenticateUser = require('./middleware/authentication')
//import routes
const authRouter = require('./routes/auth')
const jobsRouter = require('./routes/jobs')
// error handler
const notFoundMiddleware = require('./middleware/not-found');
const errorHandlerMiddleware = require('./middleware/error-handler');
app.set('trust proxy', 1)
//built in mW
app.use(
rateLimiter({
windowMs: 15 * 60 * 1000, //15 minutes
max: 100, //limit each IP to 100 request per wMs
})
);
app.use(express.json());
app.use(helmet());
app.use(cors());
app.use(xss());
// routes - full path
app.use('/api/v1/auth', authRouter)
app.use('/api/v1/jobs', authenticateUser, jobsRouter) //authUser is added to this route to prevent unauthorized access to the Jobs route and prevent editing
app.use(notFoundMiddleware);
app.use(errorHandlerMiddleware);
const port = process.env.PORT || 5000;
const start = async () => {
try {
await connectDB(process.env.MONGO_URI)
app.listen(port, () =>
console.log(`Server is listening on port ${port}...`)
);
} catch (error) {
console.log(error);
}
};
start();
THIS is my auth code
const User = require('../models/User')
const {StatusCodes} = require('http-status-codes')
const { BadRequestError, UnauthenticatedError } = require('../errors')
const register = async (req,res) => {
const user = await User.create({...req.body})//'{...req.body}' enables mongoose to do the user validation
const token = user.createJWT()
res
.status(StatusCodes.CREATED)
.json({user:{name:user.name}, token})
}
const login = async (req,res) => {
const {email,password} = req.body
if(!email || !password){
throw new BadRequestError('Please provide email and password')
}
const user = await User.findOne({email})
if(!user){
throw new UnauthenticatedError('Invalid Credentials')
}
const isPasswordCorrect = await user.comparePassword(password)
if(!isPasswordCorrect){
throw new UnauthenticatedError('Invalid Credentials')
}
const token = user.createJWT()
res
.status(StatusCodes.OK)
.json({user:{name:user.name},token})
}
module.exports = {
register,
login,
}
THIS is my routes code
const express = require('express')
const router = express.Router()
const {login,register} = require('../controllers/auth')
router.post('/register', register)
router.post('/login', login)
module.exports = router
I finally solved the challenge. This is what I did ::
I generated a new SSH public key from my computer terminal which I then linked to my heroku settings.
I then deleted the old app I had created in my heroku, cleared all existing git repos within my app terminal and quit the app. Restarted my computer and then started the heroku create and deploy app process again from the beginning. Now everything works fine.
The problem was not having an SSH linking key.
Thank you #Chris for your support.
Related
I have a React/Node app that posts to MongoDB Atlas using Axios. Locally, the app makes calls successfully, but after deploying it on Heroku, I'm getting the following error message in the console:
POST http://localhost net::ERR_CONNECTION_REFUSED; Uncaught (in promise) o {message: 'Network Error', name: 'AxiosError', code: 'ERR_NETWORK
React Frontend:
const handleClick = (event) => {
event.preventDefault();
const newConnection = {
firstName: input.firstName,
lastName: input.lastName,
email: input.email,
comments: input.comments,
date: new Date()
}
axios.post('http://localhost:3001/create', newConnection)
window.alert("Thank you! We will be in touch soon.")
}
Backend Route:
const express = require("express");
const router = express.Router();
const Connection = require("../models/connectionModel");
router.route("/create").post((req, res) => {
const firstName = req.body.firstName;
const lastName = req.body.lastName;
const email = req.body.email;
const comments = req.body.comments;
const date = req.body.date;
const newConnection = new Connection({
firstName,
lastName,
email,
comments,
date
});
newConnection.save();
})
module.exports = router;
Backend Server:
const express = require('express');
const app = express();
const cors = require('cors');
const mongoose = require('mongoose');
const path = require('path');
const port = process.env.PORT || 3001;
app.use(cors());
app.use(express.json());
app.use(express.static(path.resolve(__dirname, "./frontend/build")));
if (process.env.NODE_ENV !== 'production') {
require('dotenv').config();
}
mongoose.connect(process.env.MONGODB_URI);
app.use("/", require("./routes/connectionRoute"));
app.listen(port, function() {
console.log('express server is running on port 3001')
})
After combing the web for solutions, I confirmed that the express server is running on port 3001 and that I have CORS enabled. It's possible that there's an issue with the url I'm using in the axios.post request, but I'm unsure how to proceed.
Any help would be much appreciated!
You are trying to call localhost. once you deploy you need to call to API url.
create a way to get the API_URL from environment variable for react.
API_URL=https://your-heroku-url.com
axios.post(`${API_URL}/create`, newConnection)
Yet Another Heroku Problem....
When working in development mode, users can login to the app no problem.
In Production Mode on Heroku, this is not the case - a POST request to /api/login returns a 500 Internal Server Error.
In Production Mode, my app seems to be connected to the correct database as /api/users returns the full list of registered users.
Heroku just seems to be throwing a 500 error just for the hell of it.
Any ideas why?
The App:
app.js
require('dotenv').config()
const config = require('./utils/config')
const express = require('express')
require('express-async-errors')
const app = express()
const mongoose = require('mongoose')
const cors = require('cors')
const morgan = require('morgan');
const middleware = require('./utils/middleware')
const blogsRouter = require('./controllers/blogs')
const usersRouter = require('./controllers/users')
const loginRouter = require('./controllers/login')
mongoose.connect(config.MONGODB_URI)
.then(() => {
console.log('connected to MongoDB')
})
.catch((error) => {
console.log('error connection to MongoDB:', error.message)
})
app.use(middleware.tokenExtractor)
app.use(cors())
app.use(express.static("build"))
app.use(express.json())
app.use('/api/blogs', blogsRouter)
app.use('/api/users', usersRouter)
app.use('/api/login', loginRouter)
app.use(middleware.errorHandler)
app.use(middleware.unknownEndpoint)
app.use(morgan(':method :url :body'));
module.exports = app
index.js
require('dotenv').config()
const app = require('./app')
const http = require('http')
const logger = require('./utils/logger')
const config = require('./utils/config')
const server = http.createServer(app)
const PORT = process.env.PORT
server.listen(PORT, () => {
logger.info(`Server running on port ${config.PORT}`)
})
loginRouter
const jwt = require('jsonwebtoken')
const bcrypt = require('bcrypt')
const loginRouter = require('express').Router()
const User = require('../models/user')
loginRouter.post('/', async (request, response) => {
const { username, password } = request.body
const user = await User.findOne({ username })
const passwordCorrect = user === null
? false
: await bcrypt.compare(password, user.passwordHash)
if (!(user && passwordCorrect)) {
return response.status(401).json({
error: 'invalid username or password'
})
}
const userForToken = {
username: user.username,
id: user._id,
}
const token = jwt.sign(userForToken, process.env.SECRET)
response
.status(200)
.send({ token, username: user.username, name: user.name })
})
module.exports = loginRouter
The loginRouter contains the following line necessary for generating a token:
const token = jwt.sign(userForToken, process.env.SECRET)
Heroku does not know what process.env.SECRET is unless you tell it.
Go to your app page in Heroku ---> Settings ---> Reveal Config Vars
Click Add
Type SECRET into KEY and your value into VALUE
This then fixes the code.
I deployed my API to Heroku and when I try to use it (login). I get some errors.
my code -
const express = require("express");
const app = express();
const mongoose = require("mongoose");
const dotenv = require("dotenv");
const cors = require("cors");
// IMPORT FILES
const user = require("./routes/user");
// MONGOOSE CONNECTION
mongoose.connect(
"CONNECTION URL HERE",
{ useNewUrlParser: true },
() => {
console.log("Connected to DB");
}
);
// MIDDLEWARE CONFIGS
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
mongoose.Promise = global.Promise;
// ROUTES REDIRECTION
app.use("/", user);
// SERVER
const server = app.listen(process.env.PORT || 8080, () => {
const port = server.address().port;
console.log(`Server is running on port ${port}`);
});
JWT FILE
const jwt = require("jsonwebtoken");
module.exports = function (req, res, next) {
const token = req.header("token");
if (!token) return res.status(401).send("please login again");
try {
const verify = jwt.verify(token, "JWT SECRET HERE");
req.user = verify;
next();
} catch (err) {
res.status(400).send("invalid token");
}
};
Some pictures of errors-
Error in Heroku logs --tails
error is browser
PS: i had .env for the variables but took 'em out for delpoyment's sake as I was getting Application error.
thank you! help is appreciated.
Have you added your environment variables to heroku config vars?
If not then follow the heroku documentation to do so.
https://devcenter.heroku.com/articles/config-vars
You can use the heroku cli or use the heroku dashboard to add the variables. Refer the docs for a detailed explanation.
Context: I am using mongoDB to store my data on my first API, it's made in node.js. I'm currently working on creating a login system. When I post the account to my API I set the _id value to the email address so to access it I can just do api.com/logins/email. Whenever I do that I get this in return
{"_id":"email","password":"password","__v":0}
However when I switch the server location (from my server to my laptop for dev testing) I can no longer access the logins by _id. I can still access the entire collection, but when I attempt to call specifically by the _id I get Cannot GET /logins/email This also happens if after the fact I reopen the API server on my personal server
In order to fix this I have to delete all the collections in that area and re add one from the app. Once I do this everything works again however when my app goes live I would want to have this fixed because otherwise everyone would need to remake their accounts when I do work on the API
With this being my first API I'm kind of at a loss for what's happening and why it is, any help would be appreciated
Relevant code from sign in page (yes I am aware that base64 isn't encrypting I just haven't change it yet)
const login = async () =>{
encrypted = (await encrypt())
console.log(email.toUpperCase())
var mail = email.toUpperCase()
var test = await fetchSingleData(url,mail)
console.log(test)
if (test==null){
console.log("Invalid email")
return
}
console.log(test.password == encrypted)
if (encrypted == test.password){
console.log("I'm in")
setEmail("")
setPassword("")
navigation.navigate("Sheet")
}
else console.log("Invalid Password")
}
const encrypt = async () =>{
var enc = Base64.encode(password)
console.log(enc)
return enc
}
Mongoose connection code
const express = require('express')
const app = express()
const mongoose = require('mongoose')
require('dotenv/config')
const bodyParser = require('body-parser')
const MONGOBD_URL = process.env.DB_CONNECTION
var https = require("https")
var fs = require("fs");
var path = require("path")
app.use(bodyParser.json())
//Import routes
const postsRoute = require('./routes/posts')
const loginRoute = require("./routes/logins")
app.use('/posts', postsRoute)
app.use('/logins', loginRoute)
//ROUTES
app.get('/',(req,res)=>{
res.send("We are on home")
})
//LISTENER
app.listen(19010)
//Connect to DB
mongoose.connect(MONGOBD_URL,{useNewUrlParser:
true},()=>{console.log("connected to DB")})
module.exports = app;```
Routing
const express = require('express')
const router = express.Router();
const Login = require("../Models/Login")
//GET ALL ACCOUNTS
router.get('/',async (req,res)=>{
console.log("req")
try{
const logins = await Login.find()
res.json(logins)
}catch(err)
{
res.json({message: err})
}
})
// CREATES ACCOUNT
router.post('/', async (req,res) => {
const login = new Login({
_id: req.body._id,
password: req.body.password
})
//SPECIFIC ACCOUNT
router.get('/:postID', async (req,res) =>{
try{
const login = await Login.findById(req.params.postID)
res.json(login)
}
catch(err){res.json({message:err})}
})
const savedLogin = await login.save()
try{
res.json(savedLogin)
}catch(err){
res.json({message: err})
}
})
//DELETE ACCOUNT
router.delete('/:postID', async (req,res) => {
try{
const remove = await Post.remove({_id:req.params.postID})
res.json(remove)
}
catch(err){res.json({message:err})}
})
module.exports = router
Data example in database
okay so let us get to this...I'm not too sure what the cause of this issue is, but let us go through your code and try to isolate it. So we will begin by neatening things up a little.
starting with your login code:
const login = async () => {
encrypted = (await encrypt())
var mail = email.toUpperCase()
var test = await fetchSingleData(URL, mail)
// [TIP]: this is sufficient to achieve the same logic.
if (!test) {
return
}
if (encrypted == test.password) {
setEmail("")
setPassword("")
navigation.navigate("Sheet")
}
else
console.log("Invalid Password")
}
//...
const encrypt = async () => {
return Base64.encode(password)
}
Okay let check out your route configuration.
// [TIP]: import everything first
const express = require('express')
const mongoose = require('mongoose')
const bodyParser = require('body-parser')
// [TIP]: const on everything that wont change
const https = require("https")
const fs = require("fs");
const path = require("path")
require('dotenv/config')
const MONGOBD_URL = process.env.DB_CONNECTION
const app = express()
app.use(bodyParser.json())
//Connect to DB
// [FIX]: Connect to the database first before referencing it in your routes
// [NOTE]: Express is a static server and cannot change after configuring
// the routes that you have.
mongoose.connect(MONGOBD_URL,
{ useNewUrlParser: true },
() => console.log("connected to DB"))
//Import routes
const postsRoute = require('./routes/posts')
const loginRoute = require("./routes/logins")
// I do not know what goes on here
app.use('/posts', postsRoute)
// or here, but suspect your issue lies here.
app.use('/logins', loginRoute)
//ROUTES
app.get('/', (req, res)=>{
res.send("We are on home")
});
//LISTENER
app.listen(19010, () => console.log('server listening on port 19010'));
module.exports = app;
Im still not sure what the problem could be with this code, my suspicion is still with your database connection.
So in the end the issue was my brackets. They were set up in a way that so that the singular get was only created when I did a POST
I have making an API using express and node.
Here is my app.js
const express = require('express');
const bodyParser = require('body-parser');
const dotenv = require('dotenv');
// setup dotenv to read environment variables
dotenv.config()
// Load Environment Varibles
const env = require('./utils/env');
// INIT MONGODB CONNECTION
require('./mongoose');
// create a new express application
const app = express();
// setup bodyparser middleware to read request body in requests
// we're only reading JSON inputs
app.use(bodyParser.json());
// Listen to API routes
const apiRoutes = require('./routes')
app.use('/api', apiRoutes);
// Start listening to requests
app.listen(env.PORT, () => {
console.log(`Server started on PORT ${env.PORT}`);
});
And here is the API routes that are being imported
const express = require('express');
const apiController = require('./apiController');
const apiValidator = require('./apiValidator');
const router = express.Router();
router.post('/login', apiValidator.loginUserValidator, apiController.loginUserController);
router.get('/rand', (req, res) => {
res.send('Some randon text');
});
module.exports = router;
Here is the middleware
const {
failureResponse
} = require('./../utils/response');
const errorcodes = require('./../utils/errorcodes');
const loginUserValidator = (req, res, next) => {
const user = req.body;
if (!user.username) {
return res.status(400).json(failureResponse(errorcodes.ERROR_INVALID_BODY_PARAMETER, "Invalid username"));
}
if (!user.password) {
return res.status(400).json(failureResponse(errorcodes.ERROR_INVALID_BODY_PARAMETER, "Invalid password"));
}
if (user.authTokens) {
delete user.authTokens;
}
next();
};
module.exports = {
loginUserValidator
};
Here is the controller
const User = require('./../models/user');
const {
successResponse,
failureResponse
} = require('./../utils/response');
const errorcodes = require('./../utils/errorcodes');
const loginUserController = async (req, res) => {
try {
const user = req.body;
// find if the user already exists
const existingUser = await User.findOne({
username: user.username
});
if (existingUser) {
// user exists. generate token and login user
console.log('Existing user login');
const token = existingUser.generateAuthToken();
return res.status(200).json(successResponse(token));
} else {
console.log('New user login');
const savedUser = await new User(user).save();
const token = savedUser.generateAuthToken();
return res.status(200).json(successResponse(token));
}
} catch (e) {
console.log(e);
return res.status(400).json(failureResponse(errorcodes.ERROR_SERVER_ERROR, "Unable to login user"));
}
};
module.exports = {
loginUserController
};
Here the issue is when I try to hit the login route from Postman, I am getting an error which says Could not get any response.
But when I hit the rand route, the output is correct.
So the issue isn't the arrangement of the code.
Why am I not able to use the login route here?