Store webhooks functions inside a master function - node.js

I have set up multiple webhook endpoints that follow the similar structure in Node.js: 1) stringify the JSON request and 2) do something about that stringified request in R.
This consequently leads to a lot of duplicate code, and I attempt to stay DRY by creating a function in which I specify the arguments that actually do change. Here's an example.
First, the top portion of the script:
require("dotenv").config();
const express = require("express");
const app = express();
const port = 3000;
app.use(express.json());
Then, the part I would like to rewrite into a master function (WH) in which everything capitalized below between < and > becomes the argument.
app.post(<ENDPOINT>, foobar);
function foobar(req, res) {
var spawn = require("child_process").spawn;
let body = JSON.stringify(req.body);
var R_shell = spawn("/usr/local/bin/Rscript", [<PATH_TO_SCRIPT>, body]);
res.end("Processing completed");
}
app.get(<ENDPOINT>, (req, res) => res.send(`<html><body><h1>All working!</h1></body></html>
`));
Hence, with two endpoints, I'd end up with:
require("dotenv").config();
const express = require("express");
const app = express();
const port = 3000;
app.use(express.json());
WH(endpoint="foo", script_path="baz")
WH(endpoint="lorem", script_path="dolor")
P.S. Sorry if this is poorly formulated question from a Node.js standpoint—it's my first time developing with Node.js.

If I understood your question correctly, what you can do is something like this:
Firstly, you need to create a function that returns a router with the specified routes (You could create this function in a different file to make the code cleaner).
const {Router} = require('express')
function WH(endpoint, scriptPath) {
const router = Router()
function fn(req, res) {
var spawn = require("child_process").spawn;
let body = JSON.stringify(req.body);
var R_shell = spawn("/usr/local/bin/Rscript", [scriptPath, body]);
res.end("Processing completed");
}
router.post(endpoint, fn);
router.get(endpoint, (req, res) => res.send(`<html><body><h1>All working!</h1></body></html>`));
return router
}
And finally you should use it like this:
require("dotenv").config();
const express = require("express");
const app = express();
const port = 3000;
app.use(express.json());
app.use(WH("/foo", "./baz"))
app.use(WH("/lorem", "./dolor"))

Related

Why ECONNRESET error is coming in POSTMAN while making a NODEJS request

I have written a simple request response code in NODEJS but there is no response in return of the request is there .
The code for my app.js(Server file) is
const express = require('express');
const cors = require('cors')
const paymentroute = require('./routes/paymentRoutes');
const app = express();
app.use(cors);
app.use("/api",paymentroute);
app.listen(3100,()=>{
console.log(`listening to port 3100`);
})
The code for my req and res is
const express = require('express');
const router = express.Router();
// const { checkout } = require('../controllers/paymentController');
router.post("/checkout",(req,res) => {
console.log("this function is called ")
return res.json({success:"true"})
});
module.exports = router;
Even the console.log inside the res function is not working.
Just change app.use(cors); to app.use(cors());
const express = require('express');
const cors = require('cors');
const paymentroute = require('./routes/paymentRoutes');
const app = express();
app.use(cors());
app.use('/api', paymentroute);
app.listen(3100, () => {
console.log(`listening to port 3100`);
});
I think it is a connection-related issue often related to a networking issue caused by a Virtual Private Network (VPN) that in some cases is required by some API services or, in other cases, prevents you to reach an API service.
The issue seems to be a combo of having the no-cache header enabled and a request URL length over 64 characters. If the issue persists after doing this solution then try to upgrade to the latest version of Postman.

How to structure Express server to use granular API endpoints

I currently have an Express server I'm using for a mobile app which is structured as follows (server.js):
const PostRouter = require('./api/production/Post');
const UserRouter = require('./api/production/User');
...
app.use('/posts', PostRouter)
app.use('/users', UserRouter)
and then in api/production/Post I have:
router.get('/fetch', (req, res) => {
...
}
router.get('/delete', (req, res) => {
...
}
etc..
However, I would really like to rebuild the server to match the structure of my corresponding NextJS app and its API structure, which would be something like:
/api/posts/
add-post/
index.js
fetch-all/
index.js
edit-post/
index.js
Where each index.js file contains just one endpoint/query instead of the current structure where each file has multiple queries with the router.get thing.
It looks like this is possible by creating a Router for each endpoint with something like:
const PostFetchAllRouter = require('./api/posts/fetch-all');
const PostEditPostRouter = require('./api/posts/edit-post');
...
app.use('posts/fetch-all', PostFetchAllRouter)
app.use('posts/edit-post', PostEditPostRouter)
What would be the best way to do this, please? Is there an easier way to do this without all the boilerplate in the server.js file? I'm very new to Express - please excuse if it's a naive question
You could move the "boilerplate" code to the different router files and build a router chain. But you have to write a little bit more.
server.js
|-api/
|--posts/
|---PostsRouter.js
|---fetchAll.js
|--users/
|---UserRouter.js
fetchAll.js
const express = require("express");
const FetchAll = express.Router();
FetchAll.get("/fetch", (req, res) => { res.send("/posts/fetch") });
module.exports = FetchAll;
PostsRouter.js
const express = require("express");
const FetchAll = require("./fetchAll");
const PostsRouter = express.Router();
PostsRouter.use(FetchAll);
module.exports = PostsRouter;
server.js
const express = require('express');
const PostsRouter = require("./api/posts/PostsRouter");
let app = express();
app.use("/posts", PostsRouter);
app.listen(80, () => {});
If you build it like that you would plug the small routers into the next bigger one and then use them in the server.js.
GET localhost/posts/fetch HTTP/1.1
// returns in my example the string "/posts/fetch"
Is that what you were looking for?

how to create a nodeJS module with expressJS

I'm making a nodeJS module, and I want to use expressJS as a framework for it.
I'm trying to see, how I could go by, including a function inside and app.get(); and call it via another file, such as the actual app.
var express = require("express");
var app = express();
app.get("/", function (req, res) {
exports.type = function (text) {
console.log(req.ip);
console.log(text);
}
});
now when I use this, and i call it on the actual app like:
var web = require("directory_to_file");
var express = require("express");
var app = express();
var http = require("http").Server(app);
app.get("/", function (req, res) {
web.type("Hello, world");
});
http.listen(10022, function () {
console.log("server is up");
});
I get an error:
TypeError: Property 'type' of object #<Object> is not a function
anyone know a way to make it so I can call the function?
There are generally two things you want to export as a module - an API and a Middleware. The classic example of middleware is an authentication module. To do the middleware, just export the middleware. I tend to do a little more than that so I can configure the middleware later. Something along the lines of this:
module.exports = exports = function(config) {
// Do something with config here
return function(req, res, next) {
// your middleware here
};
};
You can then use your middleware in your main program like this:
var app = require('express')(),
mymodule = require('./mymodule');
var config = {}; // replace with whatever config you need
app.use(mymodule(config));
app.listen(process.env.PORT || 3000);
To implement an API, you will create a Router object, then attach your routes to the Router object. You can then "mount" your router in your main program. For example, you could have a file called 'myroutes.js' with the following contents:
var express = require('express'),
myroutes = express.Router();
myroutes.get('/foo', (req, res) => {
res.status(200).type('application/json').send({ myparam: 'foo' });
});
module.exports = exports = myroutes;
Have the following in your main program:
var app = require('express')(),
myroutes = require('./myroutes');
app.use('/api', require('./myroutes'));
app.listen(process.env.PORT || 3000);
Here, in 'myroutes.js', I'm defining a sub-route of /foo and then in the main program, I'm mounting that on /api - so I would access /api/foo to access that API.
In your directory_to_file you are only exporting on app.get('/') which will never be called.
You could add in your directory_to_file the following code
var express = require('express');
var router = express.Router();
router.get('/', function(req, server) {
console.log(req.ip);
});
module.exports = router;
And in your main file you could use app.use('/', web)
A short explanation:
You are creating a new express app / config in your directory_to_file file which won't be launched or used. So your app.get event won't be fired once.
That's why web.type is not a function. You are not exporting anything.
Use the way I provided. This is a commonly used method.
You could call the code I provided a "route". Create multiple routes / route files and include them in your main method.
Your code just looks confused. If I understand you correctly, what you are really trying to do (at least in Node/express terminology) is write your own middleware.
Express is designed with this in mind and it's pretty straightforward e.g.
ipLogger.js
module.exports = function(req, res, next) {
console.log(req.ip);
next();
}
app.js
var http = require("http")
, express = require("express");
, app = express()
, server = http.Server(app)
, ipLogger = require("./ipLogger.js");
app.use(ipLogger()); // log IP of all requests
// handle routes
server.listen(10022, function() {
console.log("server is up");
});

require() in node.js is not working and returns error?

I have looked through stackoverflow and read about require. However I cannot understand why my require function does not run.
app.js code:
var http = require('http');
var express = require("express");
var app = express();
//Twitter Search -------------------
app.get("/tweet, function(req,res){
var twiter = require('twiter.js');
});
app.listen(3000);
twitter.js code:
console.log("twitter.js ran");
Make sure both app.js and twitter.js in same directory
And add ./ before it. Just use following
var twitter = require('./twitter'); // .js extension is not necessary
Also as alexey mentioned. twiter is not same as twitter :)
Take care of your typos. (I think I'm too lazy to read it carefully)
app.js
var http = require('http');
var express = require("express");
var app = express();
//Twitter Search -------------------
app.get("/tweet", function (req, res) {
var twitter = require('./twitter');
twitter.log();
});
app.listen(3000);
twitter.js should be exposed using module.exports
var twitter = {
log: function () {
console.log('twitter is loaded');
}
};
module.exports = twitter;
This should now print "twitter is loaded" in your console, when you visit localhost:3000/tweet

How to modularize routing with Node.js Express

I'm building a web app with Express and Node and am trying to factor my routing so that I don't have hundreds of routes in the same file. This site serves different files within the projects directory, so I made a file in routes/ called projectRoutes.jsto handle the routing for project files:
var express = require('express');
module.exports = function() {
var functions = {}
functions.routeProject = function(req, res) {
res.render('pages/projects/' + req.params.string, function(err, html) {
if (err) {
res.send("Sorry! Page not found!");
} else {
res.send(html);
}
});
};
return functions;
}
Then, in my routes.js, I have this...
var projectRoutes = require("./projectRoutes");
router.get('/projects/:string', function(req, res) {
projectRoutes().routeProject(req, res);
});
Is there a better way to structure this functionality within projectRoutes.js? In other words, how can I configure projectRoutes.js so that I can write the follow line of code in index.js:
router.get('/projects/:string', projectRoutes.routeProject);
The above seems like the normal way to handle something like this, but currently the above line throws an error in Node that says the function is undefined.
Thanks for your help!
You should use the native express router, it was made to solve this exact problem! It essentially lets you create simplified nested routes in a modular way.
For each of your resources, you should separate out your routes into several modules named <yourResource>.js. Those modules would contain all of the routing code as well as any other configuration or necessary functions. Then you would attach them in index.js with:
var apiRoute = router.route('/api')
apiRoute.use('/< yourResource >', yourResourceRouter)
For example, if you had a resource bikes:
In index.js:
var apiRoute = router.route('/api')
, bikeRoutes = require('./bikes')
apiRoute.use('/bikes', bikeRoutes)
Then in bike.js:
var express = require('express')
, router = express.Router()
, bikeRoutes = router.route('/')
bikeRoutes.get(function (req, res) {
res.send('api GET request received')
});
module.exports = bikeRoutes
From there its easy to see that you can build many different resources and continually nest them.
A larger of example of connecting the routes in index.js would be:
var apiRoute = router.route('/api')
, bikeRoutes = require('./bikes')
, carRoutes = require('./cars')
, skateboardRoutes = require('./skateboards')
, rollerskateRoutes = require('./rollerskates')
// routes
apiRoute.use('/bikes', bikeRoutes)
apiRoute.use('/cars', carRoutes)
apiRoute.use('/skateboards', skateboardRoutes)
apiRoute.use('/rollerskates', rollerskateRoutes)
Each router would contain code similar to bikes.js. With this example its easy to see using express's router modularizes and makes your code base more manageable.
Another option is to use the Router object itself, instead of the Route object.
In Index.js:
//Load Routes
BikeRoutes = require('./routes/Bike.js');
CarRoutes = require('./routes/Car.js');
//Routers
var express = require('express');
var ApiRouter = express.Router();
var BikeRouter = express.Router();
var CarRouter = express.Router();
//Express App
var app = express();
//App Routes
ApiRouter.get('/Api', function(req, res){...});
ApiRouter.use('/', BikeRouter);
ApiRouter.use('/', CarRouter);
In Bike.js:
var express = require('express');
var router = express.Router();
router.get('/Bikes', function(req, res){...});
module.exports = router;
Similarly in Car.js

Resources