HTTPS in development environment - reactjs

I use letsencrypt certificate on my server. When running my app with HTTPS=true npm start command, I have an error when browsing my app.
SecurityError: Failed to construct 'WebSocket': An insecure WebSocket
connection may not be initiated from a page loaded over HTTPS.
Here is my config:
in package.json
"start": "react-scripts start",
"prestart": "(cat /etc/letsencrypt/live/domainxxx/cert.pem /etc/letsencrypt/live/domainxxx/privkey.pem > ./node_modules/webpack-dev-server/ssl/server.pem) || :",
(running on debian 9 server)

Related

CodePipeline + Beanstalk Connection Refused React + Express Apps

I'll lay this out below in detail:
Goal
A React front-end game that uses socket.io to transfer game state data between players on the Express server.
Setup
After finding that it would be impossible/a real work-around to have both React/Express on an Amplify instance, I decided to move to CodePipeline + CodeDeploy to Beanstalk.
I have the Source coming from GitHub, a CodeBuild step, and then CodeDeploy. The CodeBuild should basically just compile based on my buildspec.yml below:
version: 0.2
frontend:
phases:
preBuild:
commands:
- npm ci
build:
commands:
- npm run build
artifacts:
baseDirectory: build
files:
- '**/*'
cache:
paths:
Although this is calling npm run build, which I'm not sure A) The CodeBuild/CodeDeploy will try to do with node start or B) If this will kick off my react-scripts build in package.json:
"scripts": {
"webpack": "webpack --production",
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
I'm assuming I want it to build the webpack bundle in CodeBuild, then CodeDeploy will call the proper run command, but it seems black boxed? Is there another config file?
Runtime Errors
I get Connection Refused, although my server.js file defaults to localhost and 8080:
var hostname = process.env.IP || 'localhost';
var port = process.env.PORT || 8080;
Web.std.out.log:
Sep 20 18:10:10 ip-172-31-41-5 web: > MyApp#0.1.0 start /var/app/current
Sep 20 18:10:10 ip-172-31-41-5 web: > react-scripts start
Sep 20 18:10:12 ip-172-31-41-5 web: #033[34mℹ#033[39m #033[90m「wds」#033[39m: Project is running at http://172.31.41.5/
Sep 20 18:10:12 ip-172-31-41-5 web: #033[34mℹ#033[39m #033[90m「wds」#033[39m: webpack output is served from
Sep 20 18:10:12 ip-172-31-41-5 web: #033[34mℹ#033[39m #033[90m「wds」#033[39m: Content not from webpack is served from /var/app/current/public
Sep 20 18:10:12 ip-172-31-41-5 web: #033[34mℹ#033[39m #033[90m「wds」#033[39m: 404s will fallback to /
Sep 20 18:10:12 ip-172-31-41-5 web: Starting the development server...
Ngnix error.log: 2020/09/18 03:07:30 [error] 4436#0: *1 connect() failed (111: Connection refused) while connecting to upstream, client: 172.31.40.133, server: , request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:8080/", host: "172.31.41.5"
Lot of moving parts so I'm sure there are several missteps here, not sure which is which.
Based on the comments.
By default EB will look for package.json to run your application. If it is missing, and will use use script option in your package.json to start your application. For example, if you start sample node.js application that EB provides, the file is:
package.json
{
"name": "Elastic-Beanstalk-Sample-App",
"version": "0.0.1",
"private": true,
"dependencies": {},
"scripts": {
"start": "node app.js"
}
}
If you don't provide package.json nor Procfile (other option, see below) EB will expect app.js or server.js to be present to start your application.
If you don't want to use package.json, you can also use Procfile to tell EB how to start your application.
When you don't provide a Procfile, Elastic Beanstalk runs npm start if you provide a package.json file. If you don't provide that either, Elastic Beanstalk looks for the file app.js or server.js, in this order, and runs it.
Example in your case could be
web: serve -s build

Change hostname from localhost to sth to enable google reCAPTCHA domain on mac

I was trying to use google reCAPTCHA on my gatsby project.
I would like to use it on my local server without inserting my localhost domain on it.
So i added site domain name on my /etc/hosts and changed local server name using
"scripts": {
"build": "gatsby build",
"develop": "gatsby develop -H mydomain.com -p 8000",
"format": "prettier --write src/**/*.{js,jsx}",
"start": "npm run develop",
"serve": "gatsby serve",
"test": "jest",
"deploy": "gatsby build --prefix-paths && gh-pages -d public"
},
I started the dev server using npm start and the local server was on.
You can now view xxx-xxx in the browser.
⠀
http://your-domain.com:8000/
⠀
View GraphiQL, an in-browser IDE, to explore your site's data and schema
⠀
http://your-domain.com:8000/___graphql
but when i go to http://your-domain.com:8000, it gives me error:
This site can’t be reached.
This is my hosts file
##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting. Do not change this entry.
##
127.0.0.1 your-domain.com
...
When i visit localhost:8000, it works.
I am not sure why this is still on localhost other than your-domain.com.
Thanks in advance.

Heroku app w/ socket.io refuses connection or sends 404

After days of trying to figure out what's wrong, I came here to seek help.
My Heroku app is using React as frontend and Socket.io as backend. Here's the drill:
Heroku runs dyno with command "npm run start", which is set to concurrently 'npm run react' 'npm run server' to run both front and back ends.
But even if I make it work (can't really even explain how), it only works on my computer. If I try going to the same page on my phone, no requests are made and I can't even tell why, since there is no debug log.
Here is my /src/server/index.js file:
const express = require("express");
const app = express();
const server = require("http").Server(app);
const io = module.exports.io = require('socket.io')(server)
const port = process.env.PORT || 80
const socketManager = require('./SocketManager') // All functions there
io.on('connection', socketManager);
// app.use(express.static(__dirname + '/../../build'))
server.listen(port,() => {
console.log("Listening on port", port)
})
I use config file to dynamically change for the server url.
let server = 'https://hidden-waters-73936.herokuapp.com/socket.io/?EIO=4&transport=websocket'; // 404
// let server = window.location.hostname; // 404, same as above
// let server = 'http://localhost:4001'; // works locally on heroku
// let server = '/'; // 404, not found, AND CONNECTION_REFUSED
// let server = 'https://127.0.0.1:4001'; // CONNECTUIN_REFUSED
// let server = 'http://0.0.0.0:4001'; // Doesn't work at all
module.exports = server;
Commented out lines are those that I tried. Last try was changing https to ws, as someone recommended earlier, then I tried adding .com:80/socket.io..., but still no luck. Every time it's a different Error
Here's what the errors are like with uncommented server variable:
https://imgur.com/Lf0BxV3
I expect it to make successful requests both on my computer and phone. I'll try my laptop to see the logs and check back if I find anything useful.
**UPDATE for #Ashish
React component
import server from '../../config/serverConfig'
const socket = socketIOClient(server);
componentDidMount() {
socket.emit("test", {});
}
** EDIT:
My Heroku logs seem to tell me something else is going on:
2019-05-13T16:59:55.472135+00:00 app[web.1]: [1] [33m[nodemon] 1.19.0[39m
2019-05-13T16:59:55.474073+00:00 app[web.1]: [1] [33m[nodemon] to restart at any time, enter `rs`[39m
2019-05-13T16:59:55.475362+00:00 app[web.1]: [1] [33m[nodemon] watching: *.*[39m
2019-05-13T16:59:55.477060+00:00 app[web.1]: [1] [32m[nodemon] starting `node src/server/index.js`[39m
2019-05-13T16:59:56.164302+00:00 app[web.1]: [1] Listening on port 40497
2019-05-13T16:59:56.573081+00:00 heroku[web.1]: State changed from starting to up
2019-05-13T16:59:57.538639+00:00 app[web.1]: [0] Something is already running on port 40497.
2019-05-13T16:59:57.585807+00:00 app[web.1]: [0] npm run react exited with code 0
2019-05-13T17:01:19.780332+00:00 heroku[router]: at=error code=H12 desc="Request timeout" method=GET path="/" host=hidden-waters-73936.herokuapp.com request_id=42a6c345-94b7-441a-afde-82c1e9c52e97 fwd="90.191.14.93" dyno=web.1 connect=1ms service=30004ms status=503 bytes=0 protocol=https
Solution:
At least for me it works for now. Here's what I changed:
server config file (AKA what client is listening for)
let server = window.location.hostname;
const env = process.env.NODE_ENV;
if (env === 'development') {
server = 'http://localhost:4001';
console.log("Using dev port")
}
module.exports = server;
package.json
"scripts": {
"client-install": "npm install",
"start": "node src/server/index.js",
"server": "nodemon src/server/index.js",
"client": "npm start",
"build": "react-scripts build",
"react": "react-scripts start",
"dev": "concurrently \"npm run server\" \"npm run client\"",
"heroku-postbuild": "NPM_CONFIG_PRODUCTION=false npm install && npm run build"
Heroku procfile:
web: npm start
HOWEVER.
I use React Router to navigate through different pages. As soon as a page is refreshed on heroku, it returns "Not found". I suppose it is looking for a .html file with the path name, but I need it to rewrite to index.html like Firebase does.
I tried using create-react-app-buildpack, with the nginx thing and it seems to crash my server with
Failed to load resource: the server responded with a status of 405 (Not Allowed)
and then changes listening point (I suppose)
polling-xhr.js:269 POST https://XXXXXXXXXX.herokuapp.com/socket.io/?EIO=3&transport=polling&t=MgpToRX 405 (Not Allowed)
Is there a way to determine why the problem is occuring? Heroku logs dont seem to tell anything useful.

How to compress build with/without ejecting create-react-app. Also include compressed file into script tag into index.html

I'm using react-scripts build to make production ready build and to deploy it on AWS server I'm using GENERATE_SOURCEMAP=false yarn build && aws s3 sync build/ s3://*********
Is there any way to apply gzip compression to build files and include gzipped files into index.html and deploy it on aws so that in browser gzipped files would be served.
Install gzipper package (https://www.npmjs.com/package/gzipper).
Modify build command like this
"build": "react-scripts build && gzipper --verbose ./build"
and build your project you will get both gzip and regular file. It is upto you to make server to serve gzip instead of regular file. If you are using nginx you have to setup your server in nginx.conf file as below
server {
# Gzip Settings
gzip on;
gzip_static on; # allows pre-serving of .gz file if it exists
gzip_disable "msie6"; # Disable for user-agent Internet explorer 6. Not supported.
gzip_proxied any; # enable gzip for all proxied requests
gzip_buffers 16 8k; # number and size of buffers to compress a response
gzip_http_version 1.1;
gzip_min_length 256; # Only gzip files of size in bytes
gzip_types text/plain text/css text/html application/javascript application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon;
gunzip on; # Uncompress on the fly
listen 4000;
server_name localhost;
location / {
root html/react-app;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
You can add post build compression to your create-react-app build with minimal configuration using compress-create-react-app. It compresses all html, css and javascript files in the build folder using brotli and gzip algorithms.
First install it as dev dependency:
npm install compress-create-react-app --save-dev
Then edit the build command in your package.json:
"scripts": {
"start": "react-scripts start",
- "build": "react-scripts build",
+ "build": "react-scripts build && compress-cra",
"test": "react-scripts test",
"eject": "react-scripts eject"
}
That's it. Your app will be compressed when you build it.
Disclaimer: I'm the author of compress-create-react-app
I used this command to gzip files keep them the same name
- yarn global add gzipper
- gzipper compress ./build ./gzip_build --output-file-format [filename].[ext] --verbose
FYI: gzipper --verbose got me an error. Missed "compress".
You could also just add a postbuild script in your package.json with:
"postbuild": "find ./build -type f -name '*.css' -o -name '*.js' -exec gzip -k '{}' \\;"
It's not really easy to change cra build process, you can eject it but you'll have to create your own after. But, in your package.json you can define a task to be launched after the build :
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"postbuild": "node yourNodeGzipScript.js" }
Hope it can help.

webpack-dev-server open and host opens wrong URL

Per the docs here and here, I have the following in my package.json
"scripts": {
"start": "webpack-dev-server --host 0.0.0.0 --open",
...
With just --open it opens localhost:8080 when I run npm start. When I add in --host 0.0.0.0 it still opens, but opens 0.0.0.0:8080 and gives me ERR_EMPTY_RESPONSE in the browser. I can manually change it to localhost:8080 and it loads the page just fine.
I tried --host 0.0.0.0 --open --open-page localhost:8080 and it dutifully opens http://0.0.0.0:8080/localhost:8080 for me in the browser.
Has anyone gotten these two options to play nicely together?
Below works fine for me
webpack-dev-server -p --public 127.0.0.1:9000 --host 0.0.0.0 --port 9000
--host is the listening interface. --public is for what would be opened in the browser. And --open-page is for appending the page url after the main domain

Resources