It's the first time I use Node.js and Express.
I would create a web scraping.
This is my project structure:
WebScrape:
|_ bin
|_ node_modules
|_ public
|_ routes
|_ view
|_ app.js
|_ package.js
|_ package-lock.json
I've created a scrape.js file inside routes directory:
var express = require('express');
var fs = require('fs');
var request = require('request');
var cheerio = require('cheerio');
var app = express();
app.get('/scrape', function(req, res) {
// the URL we will scrape from - in our example Anchorman 2
url = 'http://www.imdb.com/title/tt1229340/';
/**
* The structure of our request call.
* The first parameter is our URL.
* The callback function takes 3 parameters: an error, a response status code and the html.
*/
request(url, function(error, response, html) {
// check to make sure no errors occurred when making the request
if(!error) {
// utilize the cheerio library on the returned html which will essentially give us jQuery functionality
var $ = cheerio.load(html);
// finally, we'll define the variables we're going to capture
var title, release, rating;
var json = { title : "", release : "", rating : ""};
}
}) // end request
}) // end get
app.listen('8081')
console.log('Magic happens on port 8081');
exports = module.exports = app;
How can I test it? Is this the right place to put it?
var express = require('express');
var fs = require('fs');
var request = require('request');
var cheerio = require('cheerio');
var router = express.Router();
router.get('/scrape', function(req, res) {
// the URL we will scrape from - in our example Anchorman 2
url = 'http://www.imdb.com/title/tt1229340/';
/**
* The structure of our request call.
* The first parameter is our URL.
* The callback function takes 3 parameters: an error, a response status code and the html.
*/
request(url, function(error, response, html) {
// check to make sure no errors occurred when making the request
if(!error) {
// utilize the cheerio library on the returned html which will essentially give us jQuery functionality
var $ = cheerio.load(html);
// finally, we'll define the variables we're going to capture
var title, release, rating;
var json = { title : "", release : "", rating : ""};
}
}) // end request
}) // end get
exports = module.exports = router;
Generally, app.js listens on ports for requests. You use express.Router to further extend and add routes in seperate router files.
In app.js you have to do this to actually add the routes:
const routes = require('./routes/scraper.js');
// app is the express() app
app.use(routes);
Related
Im setting up a web app in express.js and to keep everything organized i want to keep each route on it's own separate file and keep those files in two folders, one for GET and one for POST. How would i go about doing this?
I want to have a main server.js file and a folder with two subfolders one for GET and one for POST that contain one file for each route
Heres a diagram:
server.js
routes/
├── get/
│ ├── login.js
│ ├── register.js
│ └── home.js
└── post/
├── login.js
└── register.js
Using express.Router() will allow you to seperate your handlers into different files. you can simply include them in your main server.js
simply export the custom router.
i would recommend keeping related functionality together rather than splitting the get and post routes into different directories. for example you might have users.js which handles user related tasks and another documents.js for documents etc. you may also add an app to an app. and routes to other routes.
try
$ npm install -g express-generator
$ express-generator
example:
server.js
var route1 = require('./routes/route_1'); // Include custom router 1
var route2 = require('./routes/route_2'); // Include custom router 2
var app = express();
app.use('/route1', route1);
app.use('/route2', route2);
route_1.js
var express = require('express');
var router = express.Router();
router.get('/', function(req, res, next) { // handle specific get/post/etc methods
...
});
module.exports = router;
route_2.js
var express = require('express');
var router = express.Router();
router.get('/', function(req, res, next) {
...
});
module.exports = router;
A Domain Driven Design Approach
So principles of DDD (Domain Driven Design) will encourage keeping things that belong together, together (in this case in Domain specific folders). However, I agree with #Fattie in that keeping all the routes together is better. For example, your NodeJS project may be an API and you can easily see all the endpoints served. This isn't breaking DDD. But here's how you can keep it lean:
# routes.js
const express = require('express');
const bodyParser = require('body-parser');
const { feature } = require('./router-utils');
const router = express.Router();
router.use(bodyParser.json());
router.use(bodyParser.urlencoded({ extended: true }));
// Easy to see the route and what feature controls it.
router.get('/api/foo/bar/:something', feature('foo/bar'));
router.get('/api/foo/baz/:something', feature('foo/baz'));
router.get('/api/blah/blaaaah/:something', feature('blah/whatever'));
module.exports = router;
# router-utils.js
const cookie = require('cookie');
const auth = require('../auth/authorization');
const feature = (name, data = {}) => async (request, response, next) => {
// Do middleware stuff with cookies
const cookies = cookie.parse(request.headers.cookie || '');
// Do middleware stuff with payloads
if (request.url.includes('/some/path/here') && request.body?.payload) {
request.body = JSON.parse(request.body?.payload);
}
const { something } = request.body || '';
// Exit and continue to next routes if something is wrong.
if (something_wrong_here) {
next();
return null;
}
const Feature = require(`../features/${name}/${name.split('/').pop()}`);
// Pass all data to the feature.
return new Feature({ request, response, next, data }).handle();
};
module.exports = { feature };
# /features/foo/bar.js
const Query = require('../../common/query');
class Bar extends Query {
constructor(props) {
// Attach the request object to "this.request"
super(props);
}
async handle() {
let response = {};
const something = this.request.query.something;
// make some REST call to an upstream service and return the response.
// or make some database call and return the response.
}
module.exports = Bar;
An even simpler approach, just using the abilities of Node/js:
Say you have this:
app.use('/auth', async function (req, res, next) {
.. code
.. code
.. code
.. code
.. code
.. code
})
Recall you can simply do this:
app.use('/auth', someFile.someFunction {
I find this to be a very easy and clean approach. It's arguably better to have all the actual routes together in one place to look at. It may be useful in some projects.
I have created a node server that scrapes through a certain website and then returns a nicely formatted json data. Everything works perfectly fine on my localhost. But now I want to upload it to a server and get a link that returns the json data (just like an api).
How do I do that?
Below is the code outline:
var express = require('express');
var fs = require('fs');
var request = require('request');
var cheerio = require('cheerio');
var app = express();
app.get('/', gotdata);
function gotdata(req, res){
url = 'myurlhere';
request(url, inside_request);
function inside_request(error, response, html){
if(!error){
var $ = cheerio.load(html);
var title, date, permalink;
var obj = { title : "", date : "", permalink : ""};
// ALL MY CODES HERE
res.send(obj);
}
}
}
app.listen('8081');
console.log('Visit http://localhost:8081/');
exports = module.exports = app;
OUTPUT from my localhost:8081/
You can use an nginx server instead if you have a public IP on the server where you want to deploy your API.
Define a virtual host to your API from nginx configuration.
Please follow the tutorial in the following link for virtual host creation
https://gist.github.com/soheilhy/8b94347ff8336d971ad0
I am new in Koa and I am creating a demo app. I want to create an API to handle POST request, But when I console.log(ctx); then there is nothing in ctx in indexRouter.js, the console only printing empty object like {}.
I don't know why this is happening. Please anyone suggest me where I am doing wrong?
And please help me to get the request.body by POST Method.
serverKoa.js:
var koa = require('koa');
var router = require('koa-router');
var app = new koa();
var route = router(); //Instantiate the router
app.use(route.routes()); //Use the routes defined using the router
const index = require('./router/indexRouter')(route);
app.listen(3005 ,function(){
console.log("\n\nKoa server is running on port: 3005");
});
indexRouter.js:
var indexController=require('../controller/indexController');
module.exports = function (route) {
route.post('/postnew',async ( ctx, next) => {
console.log(ctx); // here printing {}
});
}
and my request object ( by postman ) is:
Method: POST,
url:http://localhost:3005/postnew
body:{
"firstName":"viki",
"lastName":"Kumar",
"userName":"vk12kq14",
"password":"098765432"
}
content-type:application/json
It looks like your code has two issues:
you're not using the "next" version of koa-router, which is required if you want to use async/await. You can install it like this:
npm i koa-router#next --save
you're not using koa-bodyparser to parse the request data:
npm i koa-bodyparser --save
To use:
var koa = require('koa');
var router = require('koa-router');
var bodyParser = require('koa-bodyparser');
var app = new koa();
app.use(bodyParser());
...
The parsed body data will be available in your route handlers as ctx.request.body.
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
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