How to create function with parameter can pass express.get() method? - javascript

app variable is defined by
const app = express();
This code is working fine:
app.get('/posts/:id', (req, res) => {
res.json( post_creator.CreatePost(req.params.id) );
});
But the below code is not working:
const post_url_with_id = '/posts/:id';
app.get(post_url_with_id, (req, res) => {
res.json( post_creator.CreatePost(req.params.id) );
});
How can i create function with parameter can pass express.get or post methods?
I want to implement like next function
function serve_post( post_url_with_id ) {
app.get(post_url_with_id, (req, res) => {
res.json( post_creator.CreatePost(req.params.id) );
});
}
Thanks for contributors.

This can be implemented by passing express app like:
// someRoute.js
function serve_post(app, post_url_with_id ) {
app.get(post_url_with_id, (req, res) => {
res.json( post_creator.CreatePost(req.params.id) );
});
}
module.exports = serve_post;
In your file where you've instantiated express (where you have app)
const app = express();
// assuming they are in same folder
const someRoute = require('./someRoute');
someRoute(app, post_url_with_id);

Related

TypeError: Prismic.getApi is not a function

i'm really struggling while trying to build a website from scratch without a framework. And now i'm integrating Prismic in through node.js, but as I'm following all the passages i'm getting stuck by this error shown in the log of the terminal: TypeError: Prismic.getApi is not a function.
As a consequence of this i can see the local website but the about link doesn't load. How can i fix that?
This is the main code related to the package.json
require('dotenv').config()
console.log(process.env.PRISMIC_ENDPOINT, process.env.PRISMIC_CLIENT_ID)
const express = require('express')
const app = express()
const path = require('path')
const port = 3000
const Prismic = require('#prismicio/client')
const PrismicDOM = require('prismic-dom')
const initApi = req => {
return Prismic.getApi(process.env.PRISMIC_ENDPOINT, {
accessToken: process.env.PRISMIC_ACCESS_TOKEN,
req
})
}
const handlelinkResolver = doc => {
// Define the url depending on the document type
// if (doc.type === 'page'){
// return '/page/' + doc.uid;
// } else if (doc.type === 'blog_post'){
// return '/blog/' + doc.uid;
// }
// Default to homepage
return '/'
}
app.use((req, res, next) => {
res.locals.ctx = {
endpoint: process.env.PRISMIC_ENDPOINT,
linkResolver: handlelinkResolver
}
res.locals.PrismicDOM = PrismicDOM
next()
})
app.set('views', path.join(__dirname, 'views'))
app.set('view engine', 'pug')
app.get('/', async (req, res) => {
res.render('pages/home')
})
app.get('/about', async (req, res) => {
initApi(req).then((api) => {
api.query(
Prismic.Predicates.at('document.type', 'about')
).then(response => {
console.log(response)
res.render('pages/about')
})
})
})
app.get('/personaggi', (req, res) => {
res.render('pages/personaggi')
})
app.get('/detail/:uid', (req, res) => {
res.render('pages/detail')
})
app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
})
You can use :
const Prismic = require('prismic-javascript')
// NB : This package has been deprecated but it's still working.
Instead of :
const Prismic = require('#prismicio/client')
OR you can use the actual setup guide of Prismic at https://prismic.io/docs/technologies/express-install
As user bmz1 mentionned, getApi() is no longer used in version 6+. Downgrade #prismicio/client.
In your package.json dependencies, replace by :
"#prismicio/client": "5.1.0"
Don't forget to run npm i to reset your dependencies

How to update content in dynamic URLs in Express?

Below have I created 3 URL's from the fn array. In real life, this would be approx 200 different filenames.
After I have created them, would I like to be able to update the content of the URL's to be either 1 or 0.
With the below PoC, the content doesn't change.
Question
Does anyone know how I can change the content of the URL's on-the-fly?
const express = require('express');
const app = express();
const fn = ['filename1', 'filename2', 'filename3'];
for (const e of fn) {
app.get(`/${e}`, (req, res) => {
res.send(e);
});
};
app.get(`/filename1`, (req, res) => {
res.send('test');
});
const port = 1900;
app.listen(port, () => {
console.log(`http://localhost:${port}/`);
});
You can create one wildcard route listener and add your logic inside of it
const express = require('express');
const app = express();
const fn = ['filename1', 'filename2', 'filename3'];
app.get("/*", (req, res) => {
// Do your logic inside
if(fn.includes(req.url.replace('/',''))) return res.send('ok');
res.status(404).send('Not Found');
});
const port = 1900;
app.listen(port, () => {
console.log(`http://localhost:${port}/`);
});

Express, using same routes with different imports?

I'm trying to make the a multi-language website. I've decided to go with data objects, to fill in all the text necessary. The routes I'm using for the 2 languages are exactly the same with only a difference in the import. Is there any way to make this happen without code duplication?
The templating engine is Express Handlebars, so if there is another solution for making a website multi-language, I'm open to implementing it :)
Thanks in advance for taking the time to read this.
The code in my routes for Sl language:
const express = require("express"),
router = express.Router(),
data = require("../Views/res/lang/sl");
router.get("/", (req, res) => {
data.Home = setupDataObject(data.Home, req.originalUrl, "Home");
res.render("homepage", data.Home);
});
router.get("/About", (req, res) => {
data.About = setupDataObject(data.About, req.originalUrl, "About");
res.render("About", data.About);
});
function setupDataObject(data, url, active) {
data.current = url.substring(4);
data.active = { [active]: true };
return data;
}
module.exports = router;
And the English version
const express = require("express"),
router = express.Router(),
data = require("../Views/res/lang/en");
router.get("/", (req, res) => {
data.Home = setupDataObject(data.Home, req.originalUrl, "Home");
res.render("homepage", data.Home);
});
router.get("/About", (req, res) => {
data.About = setupDataObject(data.About, req.originalUrl, "About");
res.render("About", data.About);
});
function setupDataObject(data, url, active) {
data.current = url.substring(4);
data.active = { [active]: true };
return data;
}
module.exports = router;
You can handle the locale in using with the url params, no ?
const express = require("express"),
router = express.Router();
router.get("/:locale/", (req, res) => {
const data = require("../Views/res/lang/" + locale);
data.Home = setupDataObject(data.Home, req.originalUrl, "Home");
res.render("homepage", data.Home);
});
router.get("/:locale/About", (req, res) => {
const data = require("../Views/res/lang/" + locale);
data.About = setupDataObject(data.About, req.originalUrl, "About");
res.render("About", data.About);
});
function setupDataObject(data, url, active) {
data.current = url.substring(4);
data.active = { [active]: true };
return data;
}
module.exports = router;

Route.delete() requires a callback function but got a [object Object]

I have node-express app where I have bunch of Routes for login, logout and signup and one Route for checking authorised Route which can be accessed only through providing authToken. I moved the Routes to separate Route file and I got the above error.
This is my Users Routes File:
const express = require('express');
const authenticate = require('./../middleware/authenticate');
const router = express.Router();
const {User} = require('./../models/user');
router.post('/',(req, res) => {
var body = _.pick(req.body,['email','password']);
var user = new User(body);
user.save().then(() => {
return user.generateAuthToken()
}).then((token) => {
res.header('x-auth', token).send(user);
}).catch((e) => {
res.status(400).send(e);
});
});
router.post('/login',(req, res) => {
var body = _.pick(req.body, ['email', 'password']);
User.findByCredentials(body.email, body.password).then((user) => {
return user.generateAuthToken().then((token) => {
res.header('x-auth', token).send(user);
});
}).catch((e) => {
res.status(400).send(e);
});
});
router.delete('/logout',authenticate, (req, res) => {
req.user.removeToken(req.token).then(() => {
res.status(200).send();
},(e) => {
res.status(400).send(e);
}) ;
});
router.get('/me',authenticate, (req,res) => {
res.send(req.user);
});
module.exports = router;
Following is my main server.js file:
const express = require('express');
const _ = require('lodash');
var app = express();
const usersRoutes = require('./routes/users');
app.use(express.json());
app.use('/users', usersRoutes);
var {mongoose} = require('./db/mongoose');
var {User} = require('./models/user');
var {authenticate} = require('./middleware/authenticate');
const port = process.env.PORT || 3000 ;
app.listen(port, () => console.log(`Listening on ${port}...`))
I have a model/Schema(mongoose) file for User so If You feel you need that I am ready to edit my question. Thanks.
The problem is that router.delete is expecting a function on the middleware parameter (like you did in your server.js file with app.use(express.json())) so it can be used like a callback which gets called whenever a request reach your route.
Try changing authenticate to authenticate().
It seems like in your users routes file you are importing the entire module who contains the authenticate function, so when try to access it like a function you'll get an error. You need to import it like you did in your server.js file.
Change the line const authenticate = require('./../middleware/authenticate'); for const {authenticate} = require('./../middleware/authenticate');.

Node.js node-postgres get JSON objects from API call

I have followed the node-postgres.org instruction at https://node-postgres.com/guides/async-express to connect via async/await to my postgres table users.
Navigating to localhost:3000/users/1 will return the JSON string for user 1 in the browser. I have extended this a bit to return all users at localhost:3000/users. My routes/user.js script is:
const Router = require('express-promise-router')
const db = require('../db')
// create a new express-promise-router
// this has the same API as the normal express router except
// it allows you to use async functions as route handlers
const router = new Router()
// export our router to be mounted by the parent application
module.exports = router
router.get('/:id', async (req, res) => {
console.log('Where id = ');
const { id } = req.params
const { rows } = await db.query('SELECT * FROM users WHERE id = $1', [id])
res.send(rows[0])
})
router.get('/', async (req, res) => {
console.log('*');
const { rows } = await db.all('SELECT * FROM users')
res.send(rows)
})
the index for this route at routes/index.js is simply:
const users = require('./user')
module.exports = (app) => {
app.use('/users', users)
}
and the db.query() and db.all() functions that I am awaiting are in db/index.js:
const { Pool } = require('pg')
const pool = new Pool()
module.exports = {
query: (text, params) => pool.query(text, params),
all: (text) => pool.query(text)
}
The routes are required in my main app.js file:
// ./app.js
const express = require('express')
const mountRoutes = require('./routes')
const cons = require('consolidate')
const path = require('path')
const bodyParser = require('body-parser')
const app = express()
mountRoutes(app)
// Assign Dust Engine to .dust files
app.engine('dust', cons.dust);
// Set .dust as the default extension
app.set('view engine', 'dust');
app.set('views', __dirname + '/views');
// Set Public Folder
app.use(express.static(path.join(__dirname, 'public')));
//Body parser and Middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: false
}));
app.get('/', function(reg, res) {
console.log('Root');
res.render('index', {hallo:'test'})
});
//Server
app.listen(3000, function() {
console.log('Server Started on Port 3000');
});
So far this works beautifully! I get the JSON strings that I want and I can build upon this sort of API by extending my routes and queries.
Question:
How can I return my JSON object rows back to app.js to res.render() it there?
or
Can I do something like this anywhere in my app:
jsonVar = GetMyJson('/users/1');
console.log(jsonVar);
returns:
[
{
"id": 1,
"usr_name": "Michael"
},
{
"id": 2,
"usr_name": "Thomas"
},
{
"id": 3,
"usr_name": "Paul"
}
]
I could then pass whatever route and parameters I want into GetMyJson() and deal with the resulting JSON.
This may be a trivial question for javascript devs ...
Thanks!
EDIT 21/12/2017
I have created a frontend script called graphs.js that simply logs my result when i call the fuction api('/user/1').
var el = document.getElementById("clickMe");
if (el.addEventListener)
el.addEventListener("click", api, false);
else if (el.attachEvent)
el.attachEvent('onclick', api);
var api = function(what){
// Action
sendRequest(what, function(result){
if(result){
log(result);
}
})
}
var apiEndpoint = 'http://localhost:3000/'
function sendRequest(_path, cb) {
var oReq = new XMLHttpRequest();
oReq.open('GET', apiEndpoint+_path);
oReq.onreadystatechange = function() {
if (this.readyState === 4) {
cb(JSON.parse(this.response));
}
else{
cb(null);
}
}
oReq.send();
}
function log(msg){
console.log(msg);
}
BUT
Is that a proper way of doing it in javascript?
The way to go about it would be something like this:
router.get('/', async (req, res) => {
console.log('*');
const { rows } = await db.all('SELECT * FROM users')
res.render('user', rows)
});
Instead of res.send you do res.render
You have to get it from database. Making self call will not be an ideal solution. So you can do following
const db = require('../db') // fix the location of db.js
app.get('/', function(req, res) {
db.all('SELECT * FROM users').then(function({ rows }) {
res.render('index', rows)
})
})
Best would be to make an userRepository.js and add code related to db over there. Then use that repository at both places.

Categories