Heroku custom DNS API route issue in Node.js - javascript

I have a custom domain set up in Heroku which works fine.
I can access my site using both my app name and custom domain.
I can access a route using my standard Heroku URL, but not using the custom domain.
For example:
Works:
https://{myappname}.herokuapp.com
https://{myappname}.herokuapp.com/callback
https://{customdomain}.com
Does not work:
https://{customdomain}.com/callback
Server config:
const express = require("express");
const path = require("path");;
const callback = require("./callback");
const app = express();
// Body parser middleware
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// Serve static assets if in production
if (process.env.NODE_ENV === "production") {
app.use("/callback", callback);
// Set static folder
app.use(express.static("client/build"));
app.get("*", (req, res) => {
res.sendFile(path.resolve(__dirname, "client", "build", "index.html"));
});
}
// Init server/port
const port = process.env.PORT || 5000;
app.listen(port, () => console.log(`Server running on port ${port}`));

I know its too late but I am writing for those who face this issue in the future.
I was also facing this issue and solved through this.
Was Not Working
https://{customdomain}.com/callback
This Worked for me.
https://www.{customdomain}.com/callback

I figured this out, it was pretty simple and I feel stupid, however I will answer this here in case anyone ever has the same issue.
Problem:
I had a React route/component called Callback. This React component was calling a Node.js route also called Callback, which processes information then redirects to a new React route/component.
Simple fix was to change my React route/component to callbackPage, leaving my Node.js route as Callback.
So in summary, I had a webpage URL with the same name as a server API route. when I visited this page, instead of the page being rendered, the API route was run and basically did nothing and timed out. I'm still confused as to why it worked with my app URL but not my custom domain.

Related

Javascript files not loading when hosting a website on digital ocean

I've built a web app with an express backend and using the ejs view engine.
When I run it on my computer it works fine but I'm trying to host in on digitalocean. I cloned it to the droplet(Ubuntu 22.10 x64) and served it on port 80. When I visited it in the browser at 46.101.145.210:80, I got these errors.
GET https://46.101.145.210/javascripts/cookieHandler.js net::ERR_CONNECTION_REFUSED
GET https://46.101.145.210/javascripts/domain.js net::ERR_CONNECTION_REFUSED
Here's my file structure,
Here's the code in index.js.
const express = require("express");
const app = express();
const fs = require("fs");
const path = require("path")
const assert = require("assert");
const PORT = 80
app.use(express.json());
app.use(express.urlencoded({extended: true}));
app.use(express.static('public'));
app.set("view engine", "ejs")
app.listen(PORT, () => {
console.log("Server running on port " + PORT.toString());
});
const domains = ... // Not important
app.get("/", (req, res) => {
res.render("index")
//res.redirect("/domain")
})
app.get("/domain", (req, res) => {
res.render("domain", {domains: domains})
})
I've tinkered with the firewall config and the express.static to see if it would make a difference. I couldn't figure anything out though.
Update: I've checked the requests out a bit. They are https requests. When I use postman and change the request to be http it works.
I solved it by adding a valid ssl certificate.
Looking your file structure and the code, I can say, you must define the full path of the public directory using
express.static(__dirname+'/public')
Or can be like
const path = require('path');
// .... your code ...
app.use(express.static( path.join(__dirname, 'public') ));
with this you are forcing to define where the public directory is on the ubuntu, and validate you are accessing your files
Hope you can solve with this
Update: checking carefully, I can see that your are trying to request using https, but your code is working on port 80 (http), so you said, on postman worked without https because of the port. If you want to have working your code with port 443 (https), you must have a certificate (with domain but not required), then try with https://46.101.145.210/javascripts/cookieHandler.js otherwhise try http://46.101.145.210/javascripts/cookieHandler.js.

Run multiple Node.js apps on the same server

I want to run multiple Node js apps on the same server, and so far I made some progress checking solutions for similar questions here (links below). Let's say I have 2 apps, each serving some html file, and I'd like to access each by visiting
https://example.com/app1 and
https://example.com/app2
So far, I have my main app, and my approach was to call this app which will then redirect a client to one of these 2 apps.
My main app looks like this:
const express = require('express');
const app = express();
app
.use('/app1', require('./app1/index.js'))
.use('/app2', require('./app2/index.js'))
.listen(80);
Each of my two sub-apps (app1 and app2) looks like this
const express = require('express');
const bodyParser = require('body-parser');
const routes = require('./routes/api');
const mongoose = require('mongoose');
require('dotenv/config');
const app = express();
mongoose.connect(
process.env.DB_CONNECTION,
{ useNewUrlParser: true, useUnifiedTopology: true }, () =>
console.log('Connected to DB')
);
mongoose.Promise = global.Promise;
app.use(express.static('public'));
app.use(bodyParser.json());
app.use('/', routes);
app.use(function (err, req, res, next) {
res.status(422).send({ error: err.message })
});
The issue is that I don't get anything after deploying these apps and visiting e.g. https://example.com/app1
I'm super new in all this so there is likely a beginner's mistake in here. Can anyone help?
Related questions How to mount express.js sub-apps? and Running multiple Node (Express) apps on same port
If you want to run totally different application in node you might use proxy_pass/reverse proxy of apache/nginx.
To do so each of your app should operate on theirs own ports and some other server (apache/nginx/etc) passing requests to each of them
example for apache: https://www.digitalocean.com/community/tutorials/how-to-use-apache-as-a-reverse-proxy-with-mod_proxy-on-ubuntu-16-04 sadly with python examples as apps, but the principle is the same.
example for nginx https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/
Im hosting several node apps using this technique and they are working really nice (nginx is much faster than apache). Also you might thinking about blocking access from internet to node apps ports directly.

Express server routes not being hit. Browser Error 'No Data Received ERR_EMPTY_RESPONSE'

I'm having an issue with my express server with an email service I was attempting to set up. After troubleshooting I decided to boil it down and attempt see if the issue would replicate with a simple 'hello world' example, which it did. No routes will be work correctly each request, whether done by a js frontend, postman, or just in a chrome browser will work. Each request will just 'spin' until it returns a 'No Data Received ERR_EMPTY_RESPONSE' error.
I've tried reinstalling the express dependency, reinstalling node itself, different browsers. The code is attached, any help would be appreciated.
const express = require('express');
const cors = require('cors');
const app = express();
let port = 3000;
app.use(cors);
app.get('/testroute', (req, res) => {
console.log('route hit');
res.send('test success');
});
app.listen(port, () => {
console.log('server started on port: ' + port);
});
Change this:
app.use(cors);
to this:
app.use(cors());
Your server was hanging because you were passing cors as middleware. But, cors by itself is not middleware. When Express called it, it never sent a response or called next() to continue routing, so therefore the client was just left hanging forever waiting for a response. Instead, the cors library is designed to that you call it as in cors() to get back a middleware function that you then pass to Express.
This is fully documented in the cors library documentation.

is it possible to provide restful service from react?

i'm working on a web project that should provide restful post service with react framework.
there are a lot of consuming rest service example on internet.
however, i want to provide restful service.
I tried the following,
1- provide service from react framework. i see it is not possible.
2- provide service from express and binding it with react via proxy
https://www.youtube.com/watch?v=v0t42xBIYIs
for this example, get method works but post method does not.
my express server like below.
const express = require('express');
const app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.post('/api/customers', (req, res) => {
res.json(req.body);
});
const port = 5000;
app.listen(port, () => `Server running on port ${port}`);
after that, , use proxy and react code like this
componentDidMount()
{
fetch('/api/customers')
.then(res => res.json())
.then(customers => this.setState({customers}, () => console.log('Customers fetched...', customers)));
at that point i get the below error
customers.js:18 GET http://localhost:3000/api/vehicles 500 (Internal Server Error)
thank you for all advice.
i'm searching for best practice.
The result of a React application build are script bundles and html files (also can include source maps for debugging) commonly referred to as build artifacts.
The best practice is simple:
When Express is involved the React app should download the build artifacts and API responses from Express (commonly called backend in this scenario).
What happens when this is not followed:
1. React frontend server (typically webpack-dev-server) is used in production. This is not a good idea, webpack-dev-serveris meant to be used in development only.
2. Browser detects that JS code from the bundles downloaded from one server (frontend) attempts to call another server (backend) and triggers a security violation which is meant to improve security. People then use CORS HTTP headers (sent by backend) to make the backend tell browsers: "Don't worry about security and don't trigger security violations, I (the backend) has been hardened to such an extent that I don't care that some code downloaded not from me tries to access me". The browser complies and this results in security needlessly watered down.
When to proxy:
In development only. The webpack-dev-server is excellent for development with its support for Live Reloading, HMR etc. To keep those advantages the backend (Express) can and should serve as a reverse proxy for the frontend. E.g. when Express receives a request for a build artifact, it should download it from the frontend first and then use it to send the response back. This ensures CORS issues do not arise.
Two issues stand out
Post vs Get
You're serving your api from a post endpoint. Change it to get.
app.get('/api/customers', (req, res) => {res.json(vehicleList);});
fetch
In the UI, it shows you are fetching from localhost:3000 when you should be fetching from localhost:5000. I assume your proxy is rerouting 3000 -> 5000 so hopefully this isn't an issue. I would however doublecheck and try hitting the localhost:3000/api/customers url (copy and paste that into the url bar) and see if you see your json.
Also
It is certainly possible to have express serve the static react bundle from a the same base url as your api.
e.g.
app.use('/', express.static('public'));
app.post('/api/customers', (req, res) => {
res.json(vehicleList);
});
Actually, I think you didn't focus that both are running on two different ports
like your server is running on Port:5000 and react project port:3000 so just add
"proxy":http://localhost:5000
//server.js (node file)***
app.get('/api/customers', (req, res) => {
const customers = [
{id: 1, Name: 'Rohan', email: 'r#gmail.com'},
{id: 2, Name: 'Rohan', email: 'r#gmail.com'}
];
res.json(customers);
});
const port = 5000;
app.listen(port, () => `Server running on port ${port}`)
// React Script***
class Customers extends Component {
constructor() {
super();
this.state = {
customers: []
};
}
componentDidMount() {
fetch('/api/customers')
.then(res => res.json())
.then(customers => this.setState({customers}, () => console.log('Customers fetched...', customers)));
}
i think there is no method for pushing data from server to client in a convensional way.
there is a good subject to push data from server to client. you may want to see that.
WebSocket vs ServerSentEvents

ngrok Cannot GET / local server up and running

I'm trying to follow Crowdbotics' Messenger bot tutorial, however. I did exactly as he mentioned but i am getting this.
My folder:
Okay so, first of all i run node index.js and get the following:
Right after that. We initialize our ngrok server by ngrok http 5000 and get the following:
But on EVERY http request i get the classic Cannot GET /.
On the hindsight, my index.js only contain:
const express = require("express");
const bodyParser = require("body-parser");
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.listen(5000, () => console.log('Webhook server is listening, port 5000'));
I can't really point out what i am doing wrong, your help is truly appreciated.
Based on your express js code, I think you haven't define the routes to '/'
add this before the app.listen on the index.js file
app.get('/', (req, res) => res.send('Hello World!'))
Your index.js has started a server that listens and respond to the HTTP protocol - but it does not "serve files" the same way a web server such as Apache does.
As #Yana notes, you need to explicitly set a route to do something, such as send a text response back.
If you want the favicon.ico file to be sent when requested, then you need to setup a static route for that as part of your index.js code.

Categories

Resources