I have a very simple express app which serves everything in the build folder for my react app. Here's the entire thing:
const express = require("express");
require("dotenv").config();
const app = express();
const port = process.env.PORT || 5000;
app.use(express.static(process.env.PUBLIC_DIR));
app.use(express.json());
app.listen(port, () => {
console.log(`Server is running on port ${port}...`);
});
When running this on my local machine, it works fine. No issues.
On my EC2 instance, I'm using NGINX as a reverse proxy. Here's what the config in my default sites-available file looks like:
location / {
proxy_pass http://localhost:5000/;
}
location /upvotes {
proxy_pass http://localhost:5002/;
}
When you just go to the main site, another express app on 5000 serves a totally unrelated Gatsby project. That works fine, no issues.
When you go to /upvotes, this express app on 5002 does serve the index.html file perfectly fine, but it doesn't serve any of the accompanying .js and .css files that are also in that directory.
Does anyone know why this could be happening?
I eventually gave up and combined the two express apps into one and handled the /upvotes route using express. 🤷
Related
I have deployed an AWS LightSail Node server with Express on it.
Starting the app on port 3000 correctly activates app.js and display in the browser the projected string (http://my.ip.address:3000):
Welcome to the Whiteboard server! this is the home page on port 3000 with base dir: /opt/bitnami/apache/htdocs/whiteboard
This is the app.js:
const express = require("express");
const app = express();
const port = 3000;
global.__basedir = __dirname;
app.use(express.json());
app.listen(port, () => {
console.log(`Whiteboard listening on port: ${port}`);
});
app.get("/", (req, res) => {
res.send(`Welcome to the Whiteboard server! this is the home page on port ${port} with base dir: ${__basedir}`);
});
However, Trying to request any file residing in the root folder (...apache/htdocs/whiteboard) such as:
http://my.ip.address:3000/Jeanette_Blog1.png
http://my.ip.address:3000/index.html
Always returns this message in the browser:
Cannot GET /Jeanette_Blog1.png
Shows as 404 error in the console.
Btw, although the path shows apache, I have actually installed node with needed modules and express - as can be seen in the app.js file up here. The apache is just part of the node image AWS LightSail creates through their partner Bitnami.
What am I missing?
An express server by itself does not serve any files by default. If you want to serve a directory or a directory hierarchy of static files, you have to use express.static() (or something similar) in a route definition.
You should not configure express.static() to point at the same directory that contains your server code because that would enable people to look at your server files. It is a popular convention to make a sub-directory (often called "/public", either below or at the same level as your server files. Here's an example with express.static() configured for a directory at the same level. You would add this line:
app.use(express.static(path.join(__dirname, "../public")));
And, it would all look like this:
const express = require("express");
const app = express();
const path = require('path');
const port = 3000;
global.__basedir = __dirname;
// serve public files
app.use(express.static(path.join(__dirname, "../public")), {index: false});
app.use(express.json());
app.listen(port, () => {
console.log(`Whiteboard listening on port: ${port}`);
});
app.get("/", (req, res) => {
res.send(`Welcome to the Whiteboard server! this is the home page on port ${port} with base dir: ${__basedir}`);
});
Then, you would move your static files such as index.html and Jeanette_Blog1.png to that /public directory. They can be referred to from the browser as URLS such as /index.html and /Jeanette_Blog1.png. The express.static() middleware will check the incoming path to see if it matches a filename in the /public directory and, if so, it will serve it. If it doesn't match a file, then it will continue routing to other route handlers you have defined.
I am writing an application and I want it to look like this
mydomain.com - react-app
api.mydomain.com - node express app
SO I created a parent folder. Inside the parent folder, i initialized npm and created my app.js file. I have also created a react app called client inside the parent folder.
I want to write my express code in the app.js file. Now I am trying to link them to run on the same port, using vhost
This is what I did in app.js
const app = express()
app.use(vhost('home.localhost', require('./client_home/src/App')))
const port = 7000
app.listen(port, () => {
console.log(`Server running on port ${port}`)
})
This doesn't run. I get some errors
How can I achieve what to want to do? Is there any best module to achieve this?
Im running a node app inside of /opt/myapp directory.
I have haproxy in front content switching on path_beg /myapp
backend server is listening on port 3000
directory structure:
/opt/myapp
index.js
package, modules
static
public
myfile.html
const express = require("express");
const path = require('path');
const app = express();
app.listen(3000, () => console.log("listening on 3000 "+__dirname+" "+process.cwd()));
app.use(express.static(__dirname+'/static/public')); //nope
//app.use(express.static('..'+'/static/public')); //nope
//app.use(express.static(path.join(__dirname, '/static/public/'))); //nope
Where __dirname outputs /opt/myapp and process.cwd() outputs /opt/myapp
I tried both concantenation and path.join with same results. Cannot GET myfile.html
curl directly on the server to http://host.com:3000 does work by returning the page,
but from browser (in front of haproxy), http://host.com/myapp/myfile.html does not work.
I suppose that I can remove the /myapp from the path in haproxy on the backend, but is there a way with express that i can account for the base directory?
This worked:
app.use('/myapp/',express.static('static/public'));
I'm trying to deploy my MERN app on Elastic Beanstalk, and I seem to be running into a final problem that I just cannot solve.
My app works fine when running my server locally (running node server), but when running on elastic beanstalk, the page never loads.
Upon inspection, the static elements are not being loaded, as seen in Dev Tools:
Image showing ERR_CONNECTION_TIMED_OUT in dev tools
I checked all the EB logs and did not find any errors or helpful messages.
I'm thinking the problem is with EB not being able to find my static files somehow. It should however, my build files are not ignored by git and are deployed to EB.
Here's some background about my project:
My backend and client code are in one project, with the following structure:
project
server.js
frontend
build
static
index.html
I run my app by building the react site, then running "node server" which runs great
Here is the relevent code from my server.js :
const port = process.env.PORT || 8081;
app.use(express.static(path.join(__dirname, 'frontend/build')));
app.get('/*', function (req, res) {
res.sendFile(path.join(__dirname, 'frontend/build/index.html'));
});
app.listen(port, () => {
console.log(`Server is running on port: ${port}`);
});
The server is successfully sending logs that the server is running and that the database has established a connection. So it seems the server is fine, it's just that the front-end is the problem.
eb config file:
option_settings:
aws:elasticbeanstalk:container:nodejs:
NodeCommand: "npm start"
aws:elasticbeanstalk:application:environment:
PORT: 8081
NODE_ENV: production
aws:elasticbeanstalk:container:nodejs:staticfiles:
/static: /frontend/build/static
I'm at a loss on how to solve this. The EB was deployed through the CLI and I haven't messed with any settings. I'm letting EB know where my static files are, and I believe it would say not found, rather than timing out.
Any help would be appreciated
Solved.
The problem was with using Helmet in my express server. I had ommited the code, thinking it not relevant, but here is the top portion of server.js, with the last line being the relevant portion:
const AWS = require('aws-sdk');
const cors = require('cors');
const express = require('express');
const helmet = require('helmet');
const mongoose = require('mongoose');
const path = require('path');
let Download = require('./models/Download.js');
require('dotenv').config();
const app = express();
const port = process.env.PORT || 8081;
app.use(helmet());
Not using helmet solves the issue.
To be honest, I'm not sure why this is the problem.
I assume that the problem is that helmet provides some security that my bare bones EB simply is not providing.
EDIT: Specifically, the problem is with CSP. Setting contentSecurityPolicy to false in Helmet is enough to fix the issue.
I am trying to upload the following to my personal server to see how it works:
https://github.com/remarkablemark/universal-react-tutorial
I have tried to change the port here: (server.js)
require('babel-register')({
presets: ['react']
});
var express = require('express');
var app = express();
app.use(express.static('public'));
app.use(require('./routes/index.jsx'));
var PORT = 80;
app.listen(PORT, function() {
console.log('http://localhost:' + PORT);
});
but when I type the corresponding url I get this:
**
Index of /ReactServer
Parent Directory
Component.jsx
client.js
public/
routes/
server.js
webpack.config.js
Apache Server at www.alessandrosantese.com Port 80
**
I can see the app working fine at http://localhost:3000/ but I would like to test it on the server (I have never deployed a react application on a live server)
This is more of deploying node.js to remote server.
I would recommend you to use heroku
Follow these steps to deploy your app easily to their servers.