Production React App Failing With 429 Error - node.js

I have built a react app webpage, i use node, express and react. I serve it within an ec2 ubuntu server with nginx, i also installed ssl and configured DNS but when I load the page, the first time it gives no problems, but when reloaded, i get this Server responded with 429 status code
The page is very simple itself, but stills failing and i can't solve the problem, i have read a lot of posts and blogs to fix it but none has worked (this only happens in production, in dev environment i get no error when running my node app).
Some of those said that you had to lazy load images and i did it, i have also tried loading components in timeout so requests are made every 1.5 seconds...
The main files that give me problems are the manifest.json and favicon.ico, they are accesible by url so i can't understand why (another 429 example).
Node server.js
Routes has nothing, just console logs
require('dotenv').config();
const express = require("express");
const app = express();
const path = require("path");
const cors = require("cors");
const allowedOrigins = [`http://localhost:${process.env.PORT}`];
var corsOptions = {
origin: function (origin, callback) {
if (allowedOrigins.indexOf(origin) !== -1 || !origin) {
callback(null, true)
} else {
callback(new Error('Not allowed by CORS'))
}
}
};
app.use(cors(corsOptions));
app.use(express.urlencoded({ extended: false }));
app.use(express.json());
app.use(express.static(path.join(__dirname, "/public")));
app.use("/", require("./routes/routes"));
app.get("*", (_, res) => res.redirect("/"))
app.listen(process.env.PORT, function () {
console.log(`Listening on port ${process.env.PORT}`);
});
App directory structure
This is my folders structure, public folder is the build that react script npm run build returns.
React app directory structure
Here you can see the structure, nothing special to what you get when run npx create-react-app. As you can see, there's a favicon.ico and manifest.json.
Manifest.json
{
"short_name": "Proximedica Bajío",
"name": "Proximedica Bajío - Oxígeno Medicinal",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}
This is all, if you need me to provide some other file it would be a pleasure.
Thanks!

Related

Deploy an Express server that uses express.static to serve a build folder to Vercel

I've implemented an express server that uses express.static to serve the build folder created from a static docusaurus site in order to apply basic authentication to access the site. This is working great locally, but I'm running into troubles when deploying to Vercel.
Currently my configuration is allowing the deployed version on vercel to render the basic auth login page, but upon successful login I am directed to a page the states: "Cannot GET /"
I belive this is likely an issue with either my vercel.json configuration, or with my vercel's template settings.
My code is as follows:
index.mjs
import express from 'express';
import dotenv from 'dotenv';
dotenv.config();
const app = express();
app.use(express.json());
const authorize = ((req, res, next) => {
const auth = {login: process.env.USERNAME, password: process.env.PASSWORD}
const b64auth = (req.headers.authorization || '').split(' ')[1] || ''
const [login, password] = Buffer.from(b64auth, 'base64').toString().split(':')
if (login && password && login === auth.login && password === auth.password) {
return next()
}
res.set('WWW-Authenticate', 'Basic realm="401"')
res.status(401).send('Authentication required.')
});
app.use('/', authorize);
app.use('/', express.static('build'));
app.listen(3000);
console.log(`🚀 Server ready at http://localhost:3000`);
vercel.json
{
"version": 2,
"builds": [{
"src": "./index.mjs",
"use": "#vercel/node"
}],
"routes": [{"handle": "filesystem"},
{
"src": "/.*",
"dest": "/"
}
]
}
package.json - start script
"start": "node --experimental-modules index.mjs",
And my vercel template is set to other, with the start script set to npm start.
Any ideas would be greatly appreciated!
I had similar issue: serve some static content and use /api routes. All worked fine in local dev but throwed "Cannot GET/" in vercel.
My solution.
Build separately serverless and static content.
Route adjustements for /api calls and static content.
My final vercel.json:
{
"version": 2,
"builds": [
{
"src": "server.js",
"use": "#vercel/node"
},
{
"src": "public/**",
"use": "#vercel/static"
}
],
"routes":[
{
"src": "/api/(.*)",
"dest": "server.js"
},
{
"src": "/",
"dest": "public/index.html"
},
{
"src": "/(.+)",
"dest": "public/$1"
}
]
}
Notes
All static content is under /public (html,css,img,js,etc)
server.js is the main app: express and route definitions. Similar to yours.
vercel build log shows:
Generated build outputs:
12:28:55.974 - Static files: 12
12:28:55.974 - Serverless Functions: 1
12:28:55.975 - Edge Functions: 0
...
12:28:58.142 Done with "server.js"
Maybe from this point you can find a solution for your case.
Ok, I've been looking for a solution for this one a little, and turns out we have to serve index.html explicitly in express:
app.get('/', (req: Request, res: Response) => {
res.sendFile('index.html', {root: path.join(__dirname, 'public')});
});
given that you probably have index.html in public folder. That's what solved the issue for me.

Express app on Firebase Functions locally

I created an Express app using Firebase Functions and am hosting the files on Firebase Hosting.
index.js (Firebase Functions):
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const express = require('express');
const parse = require('body-parser');
const cors = require('cors');
admin.initializeApp();
const app = express();
app.use(cors({ origin: true }));
app.use(parse.json());
app.use(parse.urlencoded({ extended: false }));
app.post('/create-url', (req, res) => {
console.log(req.body);
res.send(req.body);
});
exports.app = functions.https.onRequest(app);
firebase.json:
{
"hosting": {
"public": "public",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"function": "app"
}
]
},
"functions": {
"predeploy": [
"npm --prefix \"$RESOURCE_DIR\" run lint"
]
},
"emulators": {
"functions": {
"port": 5001
},
"firestore": {
"port": 8080
},
"hosting": {
"port": 5000
},
"ui": {
"enabled": true,
"port": 4000
}
}
}
When I make an HTTP request to http://localhost:5000/create-url, req.body is emtpy, but when I make a request to http://localhost:5001/PROJECT_NAME_HERE/us-central1/app/create-url (I've hidden the project name), it works properly. I'm using Postman to make the requests, but it isn't working with my front-end code either :(. If I deploy to Hosting and Functions and access the app through the web.app domain, it works. I'm running firebase emulators:start to run locally.
Thanks in advance for your help!
Check out the bottom section of this page https://firebase.google.com/docs/emulator-suite/install_and_configure. 'Generate an auth token (Hosting emulator only)'.
Basically you have to generate an auth token and pass it as a flag in your build script or add it to your ci environment variables.
Let me know if it helps!

Can't reach static public folder with ExpressJS and Zeit Now ('now dev')

I created an ExpressJS app with handlebars templating engine and starting the app via npm start looks all good to me since all assets are being loaded.
Here's my folder structure:
- public
- css
- svg
- uploads
- views
- layouts
> home.handlebars
And here's the relevant stuff of my index.js:
const express = require('express');
const exphbs = require('express-handlebars');
const path = require('path');
const fs = require('fs');
const port = 5000;
const index = express();
app.set('views', path.join(__dirname, '/', 'views'));
app.use(express.static(__dirname + '/public'));
app.engine('handlebars', exphbs({
defaultLayout: 'main',
layoutsDir: path.join(__dirname, '/', 'views', 'layouts')}
));
app.set('view engine', 'handlebars');
Here is the content of my now.json:
{
"version": 2,
"builds": [
{
"src": "index.js",
"use": "#now/node-server"
}
],
"routes": [
{
"src": "/",
"dest": "/",
"methods": ["GET"]
},
{
"src": "/justaroute",
"dest": "/",
"methods": ["POST"]
}
]
}
The Problem
As I said above using npm start shows my working app but using now dev my app can't find any assets (display a 404 in the console):
http://localhost:3000/css/icons.css net::ERR_ABORTED 404 (Not Found)
http://localhost:3000/uploads/[...].jpg 404 (Not Found).
It seems that
app.set('views', path.join(__dirname, '/', 'views'));
is setting the views path as root for the assets the views are loading.
Inside the views I load assets like this:
<link rel="stylesheet" type="text/css" href="css/icons.css">
I already tried to add /public/[...] to the assets hrefs and getting the public folder explicitly by adding app.set('public', path.join(__dirname, '/', 'public')); which resulted in Chrome still not finding the assets: http://localhost:3000/public/css/icons.css net::ERR_ABORTED 404 (Not Found)
I managed to get this working for myself with the code below. You have to serve the assets folder in both the build and route in now.json. I was serving the file in node and did not have any issue 404, so I ended up confirming it was some sort of Zeit configuration issue.
If run this with "now dev" command, theres a good certainty it will work when deployed to production.
Nb. my assets folder is nested because this site will be archived when my new site is up and running, hence it being placed in the "archive" sub directory. Change this to whatever you suits your needs.
./index.js
var express = require('express');
var server = express();
server.use('/', express.static('/src/archive'));
server.listen(8080);
./now.json
{
"version": 2,
"builds": [
{
"src": "src/archive/**",
"use": "#now/static"
},
{
"src": "*.js",
"use": "#now/node-server"
}
],
"routes": [
{
"src": "/",
"dest": "src/archive/index.html"
},
{
"src": "/(.+)",
"dest": "src/archive/$1"
}
]
}

Firebase-hosting can't get to api routes node

I have a route for '/' but it serves the public html index file instead, I tried changing the root directory of my api to /api/** but it gives me a 404 error.
it works quiet well when I run it locally but when I deploy it I run into the issue of only having the index.html file.
here is the firebase.json file
{
"hosting": {
"public": "public",
"rewrites":[
{
"source":"/api/**",
"functions":"app"
}
],
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
]
}
}
and the index.js folder
const functions = require('firebase-functions')
const express = require('express')
\\.
\\.
\\requiring routes and middleware
app.use(helmet())
app.use(express.json())
app.use(cookieParser())
app.use(cors({
origin:"*",
credentials:true
}))
app.get('/',(req,res)=>{
res.status(200).send("works");
})
app.use(locationActions)
app.use(filterActions)
app.use('/auth',userAuth)
app.use('/adm',AdminRoutes)
app.use('/prod',prodActions)
app.use('/user',userActions)
exports.app = functions.https.onRequest(app);
.send() doesn't seem to work quiet well with firebase I just have to say something like response.json({message}), this will actually send the response. also mongoose connection is prohibited as I was using a free account so any connection outside firebase is rejected.

Express app - Host on Heroku and use Parse as backend

For my express app I want to use Parse to handle all my data. As Parse's hosting options for web apps seem very limited (caped at 500 files and 500MB), I want to use Heroku to host my app. I have managed to set up my express app on Heroku, but can not quite figure out how to get access to my Parse app in it. I've searched around, but there does not seem to be too much documentation on this, and I am struggling to get it to work.
Here is my index.js for my express app:
var express = require('express');
var bodyParser = require('body-parser')
var app = express();
app.set('port', (process.env.PORT || 5000));
app.use(express.static(__dirname + '/public'));
// views is directory for all template files
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(bodyParser.json());
app.get('/', function(request, response) {
response.render('pages/public');
});
app.get('/login', function(request, response) {
response.render('pages/login');
});
// Clicking submit on the login form triggers this.
app.post('/login', function(req, res) {
Parse.User.logIn(req.body.username, req.body.password).then(function() {
// Login succeeded, redirect to homepage.
res.redirect('pages/loggedin');
},
function(error) {
// Login failed, redirect back to login form.
res.redirect('pages/login');
});
});
In app.post('/login'I have the Parse function I would use to log in users, but as Parse is not connected it just throws an error. How do I let my Express app get data from Parse?
My package.json files looks like so:
{
"name": "node-js-getting-started",
"version": "0.1.4",
"description": "A simple Node.js app using Express 4",
"main": "index.js",
"scripts": {
"start": "node index.js"
},
"dependencies": {
"ejs": "^2.3.1",
"express": "~4.9.x",
"body-parser": "1.13.x"
},
"engines": {
"node": "0.12.2"
},
"repository": {
"type": "git",
"url": "https://github.com/heroku/node-js-getting-started"
},
"keywords": [
"node",
"heroku",
"express"
],
"license": "MIT"
}
Thanks for any help!
Another hour of googling and I came across these links which proved useful:
https://medium.com/#spacekid/getting-started-with-parse-node-js-express-b2c79798cc7d
http://blog.parse.com/learn/engineering/the-javascript-sdk-in-node-js/
Before using Parse.User.logIn() and so on (or any other node.js module), you must make sure you actually include it like you include bodyParser module.
For example:
var Parse = require('node-parse-api').Parse;
Have a look at this module: Node Parse API

Resources