Express Only Serving Static Files - javascript

I am building an app with React and Express and want the routing to mainly go through Express instead of react-router.
After I built the react app and set Express to serve static files from the build folder, every path leads to only the React app. For example when visiting localhost:3000/test, I still only get the React app instead of "testing."
const express = require('express');
const path = require('path');
const app = express();
app.use(express.static(path.join(__dirname, './client/build')));
app.get('/', function (req, res) {
res.sendFile(path.join(__dirname, '/client/build', 'index.html'));
});
app.get('/test', function (req, res) {
res.send("testing");
});
app.listen(3000);

most likely you don't want such results because you want to have your server-side routes exposed to client and route which handle SPA file goes as the last route inside the application. But this code will work for you.
const express = require('express');
const path = require('path');
const fs = require('fs')
const app = express();
app.use(express.static(path.join(__dirname, './client/build')));
app.get('*', function (req, res) {
const file = fs.createReadStream(path.join(__dirname, '/client/build', 'index.html'));
return file.pipe(res);
});
app.get('/test', function (req, res) {
res.send("testing");
});
app.listen(3000);
I hope this will help, happy coding!

Related

Running an Express application inside an Express application

I have two projects. First a single page app (without bundler) which is being started by the following server.js:
const express = require("express");
const morgan = require("morgan");
const path = require("path");
const DEFAULT_PORT = process.env.PORT || 8000;
// initialize express.
const app = express();
// Initialize variables.
let port = DEFAULT_PORT;
// Configure morgan module to log all requests.
app.use(morgan("dev"));
// Setup app folders.
app.use(express.static("app"));
// Set up a route for index.html
app.get("*", (req, res) => {
res.sendFile(path.join(__dirname + "/index.html"));
});
// Start the server.
app.listen(port);
console.log(`Listening on port ${port}...`);
Secondly, I also have a separate Express application which handles authentication and has multiple routes and templates/views. However, I want one of those routes to contain the single page app instead of a simple view. I copied the whole repository of my first project into the Express applications src-directory and would now like to make it available under the route "/app".
Is that possible? How would I make sure that the static files of the single page app are being used properly?
router.js of the Express application
const getRoutes = (mainController, authProvider, router) => {
const authorizationMiddleware = require("./authorizationMiddleware");
// app routes
router.get("/", (req, res, next) => res.redirect("/home"));
router.get("/home", mainController.getHomePage);
router.get("/app", (req, res) => {
???
});
...
project structure:
-src
--first projects dir
--data
--msal-express-wrapper
--public
--utils
--views
--app.js
--authorizatonMiddleware.js
--controller.js
--router.js
-appSettings.js
-package.json
-...

Using Express and Node to connect HTML, CSS, and Javascript to a server

I have HTML, CSS, and Javascript programs that work perfectly together. I've recently realized that I'm going to need a server to be able to complete some of my functionality. I've created a local Node server using some tutorials. After reading some suggestions, I'm trying to use Express to try to add the HTML, CSS, and Javascript to the Node, which are all in the same folder. The code I have (below) just causes the browser to stay on loading.
const http = require('http');
const fs = require('fs').promises;
const host = 'localhost';
const port = 8000;
var express = require('express');
var path = require('path');
var app = express();
const requestListener = function (req, res) {
app.use(express.static(path.join(__dirname, 'public')));
//res.writeHead(200);
//res.end("My first server!");
};
const server = http.createServer(requestListener);
server.listen(port, host, () => {
console.log(`Server is running on http://${host}:${port}`);
});
you don't need http module if you are using express...
const express = require('express')
const app = express()
// '/' is the url you want to host your site
// 'public' is the folder in which you have the necessary frontend files
// and the main html should be named as 'index.html' inside 'public'
app.use('/', express.static('public'))
app.listen(5000, () => console.log('server on port 5000'))
Try this....
const express = require('express');
const app = express();
const path = require('path');
app.use(express.static(path.join(__dirname,'css'));
app.use('/html',(req,res,next)=>{
res.sendFile(path.join(__dirname,'HTML','text.html');});
app.listen(3000);

How to export file and running app

I'm trying to create 2 seperate files in my app,
one for API request, and second one for socket.io
The starting file is app.js which look like this:
const express = require('express');
const app = express();
app.get('/test', (req, res) => {
res.send('test');
});
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
module.exports = app;
and the second file for socket.io looks like this:
const app = require('./app');
const http = require('http').Server(app);
const io = require('socket.io')(http);
...
http.listen(port, function(){
console.log('listening on *: ',port);
});
When I run the app with my IDE (VSCODE) everything works perfect,
but when I'm trying to run on the terminal the app doesn't start and the page isn't available on the starting port.
I think that the problem is about the export for the socketIO file in app.js,
Any help would be appreciated.

Why am I getting "name undefined" when trying to post using Express and Body Parser

I'm attempting to build a MEAN app and trying to test POSTing with POSTMAN. When I do, I keep getting the dreaded "TypeError: Cannot read property 'name' of undefined". If I type in a simple string, the POST goes through fine. But when I use "req.body.name" I get the error. I've looked in every place and I'm not seeing my mistake. I even followed the suggestions on this thread with no luck. Any help or suggestions would be greatly appreciated.
Here's the code I am currently working with in my server.js file:
const express = require('express');
var bodyParser = require('body-parser');
var Bear = require('./models/bear')
var path = require('path');
var mongoose = require('mongoose');
var router = express.Router();
var app = express();
var staticAssets = __dirname + '/public';
app.use(express.static(staticAssets));
app.use('/api', router)
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
// Routes for my API
//===================================
// middleware to use for all requests
router.use(function(req,res,next){
// logging happens here
console.log('Something will happen.');
next(); // Head to the next router...don't stop here
});
// Test router to make sure everything is working (accessed at GET http://localhost:3000/api)
router.get('/', function(req, res){
res.json({message: 'hooray! welcome to our api!'})
})
//More routes will happen here with routes that end in "/bears"
router.route('/bears')
//Create a bear (accessed at POST http://localhost:3000/api/bears)
.post(function(req,res){
var bear = new Bear(); // Create a new instance of the bear model
console.log(req);
bear.name = req.body.name; // set the bears name (comes from the request)
//res.send(200, req.body);
bear.save(function(err){
if (err)
res.send(err);
res.json({message: 'Bear Created!!'});
});
});
//======================================
//var Products = require('./products.model.js');
var Product = require('./models/product.model');
var db = 'mongodb://localhost/27017';
mongoose.connect(db);
var server = app.listen(3000);
console.log("App is listening on port 3000");
Thanks.
Also, the url I'm trying to use inside of POSTMAN is http://localhost:3000/api/bears
Express processes requests Top-Down, meaning if you require a piece of functionality to be applied to all routes via middleware, than that middleware needs to be added to your app before any routes that require it. This is usually the case for middleware such as body-parser.
When using Router Middleware, you don't typically construct the router in the same file as the actual Express app that will use it as middleware. Instead, place it in a separate file and/or directory for organization purposes, this is considered a best practice.
Express Apps can be structured like so
/lib
/models
bear.js
product.js
/node_modules
/public
/css
/routes
api.js
package.json
server.js
The routes directory is where you would place any applicable Router Middleware files such as your api router. server.js is your main Express App and public is where your static assets are stored. lib is directory that contains any business logic files and models.
The actual Express app and Router files should look something like this
server.js
'use strict';
const express = require('express');
const bodyParser = require('body-parser');
const path = require('path');
const apiRouter = require('./routes/api');
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static(path.join(__dirname, public)));
app.use(/api, apiRouter);
app.listen(port, () => {
console.log(`Listening on port ${port});
});
module.exports = app;
routes/api.js
'use strict';
const router = require('express').Router();
const Bear = require('./lib/models/bear');
router.use((req, res, next) => {
// logging happens here
console.log('Something will happen.');
next(); // Head to the next router...don't stop here
});
router.get('/', (req, res) => {
return res.json({ message: 'hooray! welcome to our api!'})
});
router.route('/bears')
//Create a bear (accessed at POST http://localhost:3000/api/bears)
.post((req, res) => {
var bear = new Bear(); // Create a new instance of the bear model
console.log(req);
bear.name = req.body.name; // set the bears name (comes from the request)
//res.send(200, req.body);
bear.save((err) => {
if (err)
return res.send(err);
return res.json({message: 'Bear Created!!'});
});
});
module.exports = router;
To note, you could break up your API even further to increase the amount of decoupling. An example of this would be to move the /api/bear route to its own router middleware and into its own route file. Then simply add it to your routes/api.js router as a middleware like you would in server.js. If your app is going to have a decent sized API, then this would be the best approach because it would allow the most flexibility when it comes to applying middleware to only certain routes and would make maintaining the source much easier.

How to mount app.get() routes on a particular path prefix

I'm writing an API using Node.js and Express. My API has GET methods of the form:
/api/v1/doSomething
/api/v1/doSomethingElse
My code is looking something like this:
server.js:
var app = express();
...
var routes = require('./routes')
routes.attachHandlers(app, '/api/v1')
routes/index.js
...
module.exports.attachHandlers = function(app, context) {
//get a list of all the other .js files in routes
//for each route, require() it and call it myRoute
myRoute.attachHandlers(app, context)
}
routes/some-route.js
...
module.exports.attachHandlers = function(app, context) {
app.get(context + '/doSomething', doSomething)
app.get(context + '/doSomethingElse', doSomethingElse)
}
...
Effectively I'm passing the context path/mount point down through the app. If somebody were to write a route like the following, though, the context would be lost:
app.get('/doFoo', foo)
Rather than having that part of the API mounted on /api/v1/doFoo it's on /doFoo. I would like to avoid having to pass the context path around like this.
app.use supports mounting middleware on an optional mount path. I have seen references online to mounting an entire Express application on a mount path using app.use. This seems like the sort of thing I want to do, but I'm not sure how to do it or if it's the best solution for my particular use case.
To summarise - I want to mount my app.get() routes with a particular prefix by default. What's the best way of doing this?
With Express 4.0, the task is much cleaner with the Router. You can create as many routers as you need to nicely partition your app, and then attached them with app.use(). For example:
myapp.js
var express = require("express"),
router = express.Router(),
app = express(),
port = 4000;
// Here we declare our API which will be visible under prefix path
router.get('/', function (req, res) {
console.log("request to subspace hello");
res.send({ message: "Hi from subspace /api/v1/"});
});
// we attach our routes under /api/v1
app.use('/api/v1', router);
// here we have direct, root-level routing
app.get('/', function (req, res) {
console.log("request to rootspace hello");
res.send({message: "Hi from root /"});
});
app.listen(port);
console.log("App active on localhost:" + port);
Then run
node myapp.js
and visit
http://localhost:4000 and http://localhost:4000/api/v1
Here's a working example of mounting a route in Express 3:
./snipe3app.js
var express = require('express');
var app = module.exports = express();
app.get('/subapp', function (req, res) {
res.send('You are on the /sub/subapp page.');
});
./app.js
var express = require('express'),
http = require('http'),
subApp = require('./snipe3app'),
app = express();
app.use(express.favicon());
app.use(express.bodyParser());
app.use(app.router);
app.use('/sub', subApp);
app.get('/', function (req, res) {
res.send('You are on the root page');
});
http.createServer(app).listen(3000, function(){
console.log('Express server listening on port 3000. Point browser to route /secure');
});
You have to pay attention to the order in which the routes are handled when doing this.
I think express-namespace will work for this.

Categories