Cannot /GET - What's wrong with this Express Server? - node.js

I'm creating a basic app to learn Express, but can't seem to set it up right. When I run the app I get a Cannot /GET error. The basic outline is something like this:
In the top directory -
var express = require('express');
var app = express();
var getWx = require('./incoming/getWx.js');
app.set('port', process.env.PORT || 1983);
app.use('/getWx', getWx);
app.listen(1983);
Then, in /incoming/getWx.js, I have:
var express = require('express');
var app = express();
var router = express.Router();
router.route('/')
.get(function(request, response) {
// do thing here
})
module.exports = router;
Anything stand out here as wrong? Trying to do this with a router as my app will end up with multiple files.

You get that error because you probably trying to access the path / ...
Which don't have any router set to handle it...
The router you set up handles the path /getWx
If you set stomething like this:
app.use('/', getWx);
The accessing path / will return something...

Related

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?

express.Router() vs express() in express

As mentioned in express routing guide and this answer, we can create "mini-app" and use it from the main app. However I saw a code where it uses app instead of router in the module
app.js
var express = require('express');
var userRoutes = require('./routes/user');
var app = express();
app.use('/user', userRoutes);
module.exports = app;
routes/user.js
var express = require('express');
var app = express(); // not express.Router() !!
app.get('/:name', function(req, res) {
var userName = req.params.name;
res.render('user.jade', {
userName: userName
});
});
module.exports = app;
I assumed the correct usage in routes/user.js should be
router = express.Router()
instead of
app = express()
but app = express() also works! what are the differences and why router = express.Router() is better?
When you are working with a server where there are many routes, it can be confusing to leave them in a Main file together. The let router = express.Router() option works differently than let app = express().
While the app returns an app object, router will return a small app fragment, similar to the app, where you will use logic to call them later on the Main.
The most important, about your question, is that a router, which is isolated, will not interfere with others in the application, being a single environment.
https://expressjs.com/en/api.html#router
A router object is an isolated instance of middleware and routes. You can think of it as a “mini-application,” capable only of performing middleware and routing functions. Every Express application has a built-in app router.
A router behaves like middleware itself, so you can use it as an argument to app.use() or as the argument to another router’s use() method.

Express Vhost 'argument handle is required'

Firstly, found a couple of similar question on here but no duplicates, I think my situation is slightly different.
Trying to get a website and associated API working on Express using vhost for subdomians.
Here is my folder structure
/api
api.js
/server
website.js
server.js
My server.js
const vhost = require('vhost');
const express = require('express');
const app = express();
app.use(vhost('localhost', require('./server/website.js').app));
app.use(vhost('api.localhost', require('./api/api.js').app));
app.listen(1337, () => {});
My api.js
const express = require('express');
const app = express();
app.get('/', function(req, res){
res.send({ hello: 'world' });
});
module.exports = app;
Initially my path to api.js was wrong and I got a not found error so now I know my path is right but now I get the error "Typeerror: argument handle is required" whatever I do.
Any help would really be appreciated.
Your exporting the app already. So it is not necessary to add .app to the end of your require.
It should be:
app.use(vhost('localhost', require('./server/website')));
app.use(vhost('api.localhost', require('./api/api')));
Hope that helps.
here's what I did:
//used the api.localhost as the subdomain url
//it requires another express app.js to work
//the other express app must -> module.exports = app;
const vhost = require('vhost');
const app = express();
app.use(vhost('api.localhost', require('./api/app')));

How to efficiently separate routing code

Dumb/Newb question...
I am learning/working on an API in Node / Express4 and I would like to break my routes out into another module. I have it working with the following code, but it seems awkward to me to keep re-using the require('express') statement... Is there a way to move more of the code from the routes.js file into server.js and still keep my .get and .post statements in the routes module? Thanks in advance!
server.js:
'use strict';
var express = require('express');
var routes = require('./routes');
var app = express();
app.use('/api', routes);
app.listen(3000, function() {
console.log('Listening);
});
routes.js
var express = require('express'); // how do I get rid of this line?
var router = express.Router(); // can I move this to server.js?
var apiRoute = router.route('');
apiRoute.get(function (req, res) {
res.send('api GET request received');
});
module.exports = router;
Your on the right track. Its actually cool to reuse the var express = require('express'); statement each time you need it. Importing, ( requiring ), modules is a cornerstone of modular development and allows you to maintain a separation of concerns with in the files of your project.
As far as modularly adding routes is concerned: The issue is that routes.js is misleading.
In order to modularly separate out your routes you should use 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 app.js with:
var apiRoute = router.route('/api');
apiRoute.use('/<yourResource', yourResourceRouter);
For example, if you had a resource bikes:
In app.js or even a module api.js:
var apiRoute = router.route('/api')
, bikeRoutes = require('./bikes');
apiRoute.use('/bikes', bikeRoutes);
Then in bike.js:
var express = require('express');
var router = express.Router();
var 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.

Express: how to pass variables to mounted middleware

I've just started to play around with Expressjs and I'm wondering how to pass variables to mounted middleware/sub application. In the following example, I'd like the config object passed to my /blog/index
in app.js
var express = require('express');
var app = express();
//...
var config = {}
//...
app.use('/blog', require('./blog/index')
in /blog/index.js
var express = require('express');
app = module.exports = express();
app.use(express.static(...
app.get('/', function(req, res, next) {
//handle the req and res
}
Thanks,
I see two options here:
Since your blog app is an express application, you can use app.set and app.get. E.g.
blog = require('./blog/index');
blog.set('var1', value1);
blog.set('var2', value2);
...
app.use('/blog', blog);
And in blog/index.js use app.get('var1') to get the value of var1.
You can wrap the blog express application in another function that accepts configuration parameters (much like the static middleware accepts a directory name) and returns the configured application. Let me know if you want an example.
EDIT: Example for the 2nd option
app.js would look like this:
var blog = require('./blog/index');
...
var config = {};
app.use('/blog', blog(config));
and /blog/index.js like that:
var express = require('express')
module.exports = function(config) {
var app = express();
// configure the app and do some other stuffs here
// ...
return app;
}

Resources