Express routing with query String - javascript

i am currently trying node & express. The Project is a small Movie Library. Today i tryed to implement a search for titles of movies, the problem i have is when i submit my form and get my query String like this http://localhost:3000/movies/?title=Hustlers i get all the Data in my Database. But when i manually type the Url like this http://localhost:3000/movies/title=Hustlers it works fine and i get the matching result. I tryed change my Routes but i am stuck right now.
here is the movies.js
const express = require("express");
const router = express.Router();
const Movie = require("../models/movie");
//Get Back all the movies
router.get("/", async (req, res) => {
try {
const movies = await Movie.find();
res.json(movies);
} catch (err) {
res.json({ message: err });
}
});
//specific Movie
router.get("/title=:title", async (req, res) => {
try {
const movie = await Movie.find({ title: req.params.title });
res.json(movie);
} catch (err) {
res.json({ message: err });
}
});
module.exports = router;
my app.js
const express = require("express");
const bodyParser = require("body-parser");
const app = express();
const mongoose = require("mongoose");
const cors = require("cors");
require("dotenv/config");
//Middlewares
app.use(bodyParser.json());
app.use(cors());
app.use(express.urlencoded());
const moviesRoute = require("./routes/movies");
app.use("/movies", moviesRoute);
app.use(express.static(__dirname + "/"));
mongoose.connect("mongodb://localhost:27017/testDB", { useNewUrlParser: true });
app.listen(3000);
and my submit form here
<form action="/movies/">
<input type="text" name="title" />
<input
type="submit"
value="Suchen"
class="btn btn-primary btnNewMovie"
/>
</form>

The = is messing it up, because that character is reserved for the query component. It would also look much cleaner as /title/movie_title. Try this:
router.get("/title/:title", async (req, res) => {
try {
const movie = await Movie.find({ title: req.params.title });
res.json(movie);
} catch (err) {
res.json({ message: err });
}
});

There's a difference between query string params and route params.
When you submit a form, normally it will encode the request as application/x-www-form-urlencoded (More info here), then the express router parse those values and provide them thru the query hash. For more information on how to properly use the route params on express go here and read the Route parameters section.

Related

How do i get my mongo schema to export into a file then use it to insert data?

I am having trouble being able to insert data into my collection, I'm not even sure I'm doing it correctly so I apologize for the vague request but maybe my code will help you see what my intention is. The gist of it is I'm trying to make a separate file for my schema/collection and then call it from another file and insert data and call other functions etc.
file1.js file:
require('dotenv').config()
const User = require('./assets/js/data')
const bodyParser = require("body-parser");
const mongoose = require('mongoose');
mongoose.connect(process.env.url, { useNewUrlParser: true })
.then(() => {
console.log('Connected to MongoDB server');
})
// 1. Import the express module
const express = require('express');
// 2. Create an instance of the express application
const app = express();
app.set('views', './static/html');
app.set('view engine', 'ejs');
app.use(express.static('assets'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
// 3. Define the HTTP request handlers
app.get('/', (req, res) => {
res.render('main')
});
app.get('/login', (req, res) => {
res.render('login')
});
app.post('/login', (req, res) => {
console.log(req.body.number);
})
app.listen(3000, (err) => {
console.log("running server on port")
if (err) {
return console.log(err);
}
})
data.js
const mongoose = require('mongoose');
const userData = new mongoose.Schema({
phoneNumber: String,
})
const User = mongoose.model('User', userData);
module.exports(
User,
)
This line has the error.
// error
module.exports(
User,
)
module.exports is not a function.
module.exports = User
// or
module.exports = { User }
if you do the first one, then required should be like this,
const User = require('./assets/js/data')
otherwise
const { User } = require('./assets/js/data')
More about module.exports
The Data.js is correct but the way your controller works is I think the issue. If you use "const User = require('./assets/js/data')" you can use your selected variable User and then connect find, create, etc. you can use this as a reference. https://blog.logrocket.com/mern-stack-tutorial/

MongoDB Returns Empty Error Object when Making POST Request

I'm currently learning about APIs. I'm using Dev Ed's video on a RESTful MERN API. I set up my routes and I could successfully connect to my MongoDB database. However, when attempting to call save() on a post to the DB, I was returned my error message, a JSON object with a message containing the err, but my err object was completely empty.
posts.js:
const express = require('express');
const router = express.Router();
const Post = require('../models/Post');
router.get('/', (req, res) => {
res.send('We are on /posts!');
});
router.post('/', (req, res) => {
const post = new Post({
title: req.body.title,
desc: req.body.desc,
});
post.save()
.then(data => {
res.json(data);
})
.catch(err => {
res.json({ message: err });
});
});
module.exports = router;
app.js:
const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
require('dotenv/config');
const app = express();
const PORT = 8080;
app.use(bodyParser.json());
// Import Routes ------------------------
const postsRoute = require('./routes/posts');
app.use('/posts', postsRoute);
// ROUTES --------------------------------
app.get('/', (req, res) => {
res.send('We are home!');
});
mongoose.connect(
process.env.DB_CONN,
{ useNewUrlParser: true },
() => {
console.log('Succesfully connected to DB!')
});
app.listen(PORT);
Post.js (schema):
const mongoose = require('mongoose');
const PostSchema = mongoose.Schema({
title: {
type: String,
required: true,
},
desc: {
type: String,
required: true,
},
date: {
type: Date,
default: Date.now,
}
});
module.exports = mongoose.model('Posts', PostSchema);
My POST request and response (Postman):
In my code, I am attempting to send the new Post to my DB, but instead I get an error, an empty one. I either need to figure out how to view my error correctly (so that's it's not empty) or the larger problem: why my POST request is failing.
Again, I am learning about APIs, this is my very first time writing one. If there's anything I missed (like other code that you would need) or if there's something I should be doing differently, please, let me know! Thank you in advance!
use status when you want to use res like this:
for success result
res.status(200).json(data);
for .catch
res.status(500).json({ message: err });
but I prefer use async/await with try/cacth like this:
router.post('/', async(req, res) => {
const post = new Post({
title: req.body.title,
desc: req.body.desc,
});
try {
let data = await post.save()
res.status(200).json(data)
} catch (error) {
res.status(500).json({ message: error});
}
});
check the documentation of promises in mongnoos
check the connection of mongoose like this:
const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
require('dotenv/config');
const app = express();
const PORT = 8080;
app.use(bodyParser.json());
// Import Routes ------------------------
const postsRoute = require('./routes/posts');
app.use('/posts', postsRoute);
// ROUTES --------------------------------
app.get('/', (req, res) => {
res.send('We are home!');
});
runMongoose()
app.listen(PORT);
async function runMongoose(){
try {
await mongoose.connect(
process.env.DB_CONN,
{ useNewUrlParser: true }
);
console.log("mongodb is OK");
} catch (error) {
console.log("mongodb Warning", error);
}
}
if Succesfully connected to DB! printed mongoose connection is OK
the problem is that you added
{ useNewUrlParser: true }
remove that and it's gonna work fine ;)

Getting frequent error while passing data from form to a URL in NodeJS the error is cannot post /urlname

this is my from page where I post to a URL articles but it gives me error that cannot POST/URL name
every time I want to save a new article it gives me same error cannot post/URL name
<form action="/routes/articles" method="post">
//here I simply used a partials!
{{>form}}
</form>
this is code where I get data through post method that is mentioned and then it is saved to the database const express = require('express');
const router = express.Router();
const Article = require("../model/schema")
router.get('/', (req, res) => {
res.send('hey !!');
});
router.get('/new', (req, res) => {
res.render('articleGenerator');
});
router.get("/:id",(req,res)=>{
})
router.post("/",async(req,res)=>{
const newArticle = new Article({
title:req.body.title,
description:req.body.description,
markdown:req.body.markdown
})
//this code saves new article that is send from form page mentioned above
try {
newArticle = await newArticle.save();
res.redirect(`/articles/${newArticle.id}`)
} catch (error) {
res.render("/articleGenerator",{articles:newArticle});
}
})
this is my main file that i run Note that I have exported one route articlesjs that saves data.
module.exports = router;
const express = require('express');
const app = express();
const mongoose = require("mongoose");
this is for data base mongoose//
mongoose.connect("mongodb://127.0.0.1:27017/blogging-site",{
useNewUrlParser:true,
useUnifiedTopology:true,
useCreateIndex:true
})
//here i get the routes of page that is saving the data
const theRoutes = require('./routes/articles')
app.use('/theroutes', theRoutes);
app.set('view engine', 'hbs');
app.get('/', (req, res) => {
res.render('index');
});
app.listen(3000, () => {
console.log('server is up and running!!');
});

DialogFlow: How do you handle a NodeJS server with multiple routes?

I am creating a project in DialogFlow and NodeJS where I want to call my fulfillments with a webhook.
In my NodeJS server, I have multiple routes for different functions/intents. For example, /getWeather calls a weather API to return a response about the weather in a specific city. Or /getMovie calls an API to return information about a movie.
DialogFlow only allows for one webhook API, so my question is, how can I call a generic API "/" where it can handle all the different routes and call the correct route when it needs to?
I can use the inline editor on DialogFlow to call each API with the correct route; however, I want to use a single webhook rather than using the firebase functions to call the correct intents.
I can't seem to find example of this online where multiple routes are handled with a generic route.
Image of my Code Stack
index.js:
const http = require('http');
const app = require('./app');
const port = process.env.PORT || 3000;
const server = http.createServer(app);
server.listen(port);
server.post
app.js
const express = require('express');
const app = express();
const morgan = require('morgan');
const bodyParser = require('body-parser');
const mongoose= require('mongoose');
const issuesRoutes = require('./API/Routes/issues');
const movieRoute = require('./API/Routes/getmovie');
const resolvedtaskroute = require('./API/Routes/resolvedtask');
const newtaskRoute = require('./API/Routes/newtask');
mongoose.connect('link', {
useNewUrlParser: true,
useUnifiedTopology: true
})
.then(() => console.log('MongoDB connected...'))
.catch(err => console.log(err));
app.use(morgan('dev'));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use((req, res, next) => {
res.header('Acces-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', '*');
if (req.method === 'OPTIONS'){
res.header('Access-Control-Allow-Methods', 'PUT, POST, PATCH, DELETE, GET');
return res.status(200).json({});
}
next();
});
//routes to handle requests
app.use('/issues', issuesRoutes);
app.use('/newtask', newtaskRoute);
app.use('/resolvedtask', resolvedtaskroute);
app.use('/getmovie', movieRoute);
//error handling
app.use((req, res, next) => {
const error = new Error('Not Found');
error.status = 404;
next(error);
})
app.use((error, req, res, next) => {
res.status(error.status || 500);
res.json({
error: {
message: error.message
}
})
})
module.exports = app;
Example of one of my routes: getMovie.js
const express = require('express');
const router = express.Router();
const http = require('http');
router.post('/', (req, res, next) => {
const movieToSearch = req.body.queryResult.parameters.movie;
const API_KEY = 'XXXXX';
const reqUrl = `http://www.omdbapi.com/?t=${movieToSearch}&apikey=${API_KEY}`
http.get(
reqUrl,
responseFromAPI => {
let completeResponse = ''
responseFromAPI.on('data', chunk => {
completeResponse += chunk
})
responseFromAPI.on('end', () => {
const movie = JSON.parse(completeResponse)
let dataToSend = movieToSearch
dataToSend = `${movie.Title} was released in the year ${movie.Year}. It is directed by ${
movie.Director
} and stars ${movie.Actors}.
}`
return res.json({
fulfillmentText: dataToSend,
source: 'getmovie'
})
})
},
error => {
return res.json({
fulfillmentText: 'Could not get results at this time',
source: 'getmovie'
})
}
)
})
module.exports = router;
It is very clear that Dialogflow allows one webhook POST url where every call for intents are made. IF you want to use different API services inside then You should define a webhook and inside the webhook just call the functions which are related to intents using intentMAP. On each function call the external API and return the response back to dialogflow. I will describe a bit more about it using dialogflow-fulfillment.
first thing you need is a webhook POST route for handling dialogflow requests and responses and inside it you need to map intents to its specific function as like:
const { WebhookClient } = require("dialogflow-fulfillment");
const movieService= require("your function for movie API");
router.post("/", async (req, res, next) => {
const agent = new WebhookClient({ request: req, response: res });
const movie = new movieService(agent);
let intentMap = new Map();
intentMap.set("Movie Intent", () => {
//make an api call inside this function
return movie.getinfo();
});
if (agent.intent) {
agent.handleRequest(intentMap);
}
});
Now create another file for external API calls which will be like
async getMovie(){
// get all required paramters from dialogflow here and call APIS and return back response using
agent.add("The info about movie is");
}

Router not firing .find or .findByID in express app. Using nextjs as well

I am using a NextJS/MERN stack. My NextJS is using my server.js file, along with importing the routes for my API. The routes appear to be working as they do show activity when firing an API call from Postman or the browser. However, this is where the activity stops. It's not getting passed the Model.find() function as far as I can tell. I am not sure if this has to do with Next js and the prepare method in the server.js, or if this is related to the bodyparser issue.
Here is my server.js
const express = require("express");
const urlObject = require('./baseURL')
const passport = require("./nextexpress/config/passport-setup");
const passportSetup = require("./nextexpress/config/passport-setup");
const session = require("express-session");
const authRoutes = require("./nextexpress/routes/auth-routes");
const KBRoutes = require("./nextexpress/routes/kb-routes");
const userRoutes = require('./nextexpress/routes/user-routes')
const pollRoutes = require('./nextexpress/routes/poll-routes')
const mongoose = require("mongoose");
const cookieParser = require("cookie-parser"); // parse cookie header
const next = require('next')
const dev = process.env.NODE_ENV !== 'production'
const nextapp = next({ dev })
const handle = nextapp.getRequestHandler()
const bodyParser = require('body-parser');
// mongoose.connect(process.env.MONGODB_URI || 'mongodb://localhost:27017/kb', { useNewUrlParser: true });
mongoose.connect('mongodb://localhost:27017/kb')
console.log(process.env.MONGODB_URI)
const connection = mongoose.connection;
const baseURL = urlObject.baseURL
const PORT = process.env.PORT || 3000
connection.once('open', function () {
console.log("MongoDB database connection established successfully");
})
nextapp.prepare().then(() => {
const app = express();
console.log(process.env.PORT, '----port here ----')
app.use(cookieParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use("/api/auth", authRoutes);
app.use("/api/kb", KBRoutes);
app.use('/api/user', userRoutes)
app.use('/api/poll', pollRoutes)
app.get('/posts/:id', (req, res) => {
return nextapp.render(req, res, '/article', { id: req.params.id })
})
app.get('/redirect/:id', (req, res) => {
return nextapp.render(req, res, '/redirect')
})
app.all('*', (req, res) => {
return handle(req, res)
})
app.listen(PORT, err => {
if (err) throw err
console.log(`> Ready on http://localhost:${PORT}`)
})
})
// connect react to nodejs express server
And the relevant route:
KBRoutes.get('/', (req, res) => {
console.log(KB.Model)
KB.find({}, (err, photos) => {
res.json(kbs)
})
})
I am able to get to each one of the routes. Before this was working, when I had the NextJS React portion split into a separate domain therefore separate server.js files. Once I introduced NextJs thats when this problem arose. Any help would be greatly appreciated.
It looks like the relevant route is trying to return json(kbs), but kbs doesn't seem to be defined. Returning the result of your find query would make more sense to me, including a nice error catcher and some status for good practice. Catching errors should tell you what's going wrong, i would expect an error in your console anyway that would help us out finding the answer even more.
KB.find({}, (err, photos) => {
if (err) res.status(401).send(err)
res.status(200).json(photos)
})

Categories

Resources