Multiple domains and subdomains using one Angular 7 app - node.js

I have an idea for a website that I want to build myself. I have been reading in the documentation, in articles and through tutorials. But I couldn’t fully find the answers I needed.
Situation:
I have a project at AWS Lightsail (including: Angular 7, Node, MongoDB, Nginx, Express). I have multiple domain names with dynamic subdomains, used to differentiate information for employees of clients/brands. The multiple domains are part of it to make it easier to navigate and communicate.
For example:
client1.domain1.com/some/info/
client1.domain2.com/some/info/
..etc.
Setup:
I have configured the subdomains and domains through Nginx making it work with wildcard subdomains as well as declared subdomains and domains. The dynamic subdomains are configured like this:
server {
listen 80;
listen [::]:80;
server_name ~^((?<sub>.*)\.)(?<domain>[^.]+)\.com$;
root /opt/bitnami/nginx/html/$domain/$sub;
try_files $uri $uri/ /index.html$is_args$args;
}
which outputs as this directory:
/opt/bitnami/nginx/html/domain1/client1/
(client1 is in there just to test. It wouldn’t be a directory in an ideal case. Also domain1 & client1 should only be in the url as the domain & subdomain itself. not as a directory)
Thoughts:
Ideally it would be one system where each domain points to, and the content is differentiated based on the domain name and client. I thought about the following:
Have a separate app on each domain. But that would give a lot of duplicate code and work to maintain/do changes.
Have a component for each domain. But then I don’t know how to make the routing work.
Have multiple apps in one project. But Angular deploys everything in 1 HTML file with JavaScript. How do I make the routing work there?
etc.
But none really seem to work as I imagine. How do I make this work properly? How would I be able to serve the app using multiple domains in a valid, scalable & secure way?

Why not just use a single application with multiple domain bindings and then use routing within the app to segregate content. Assuming no client specific secure information is hard coded into the angular app, you should be able to create a secure application using Angular Routeing paired with a web api to make the end result you are describing.
client1.domain1.com/client/1/info/
client1.domain2.com/client/2/info/
clientx.domainx.com -> all resolve to your app
/client/ -> routes to an angular component
const routes: Routes = [
{
path: '',
children: [
{ path: 'client/:id', component: dynamicClientComponent },
]
}
];
In the angular client component you get your client ID from the url and retrieve client specific content from a web service/api
constructor(
private formBuilder: FormBuilder,
private route: ActivatedRoute,
private router: Router,
private clientService: CientService,
) {
route.params.subscribe(params => {
this.id = this.route.snapshot.params.id;
if (this.id) {
this.clientService.getById(this.id).subscribe(
(record) => {
this.ClientInfo = record;
//update UI accordingly
})
};
}
Here is a working example that illustrates this better than my code excerpt
https://stackblitz.com/edit/router-pillar1-demo-final?file=src%2Fapp%2Fapp.module.ts

if you use different domains for different info you can use different routes and insert them due to current domain location.hostname. Hope it helps https://stackoverflow.com/a/59784694/9026103

Related

Nodejs : how to redirect subdomains to ports?

I'm creating a fullstack web-app with an API as backend, and I'm hosting it on a DigitalOcean server.
The front-end (reactjs) is running on a port (3000) and the backend (express server -RESTFul API-) on another (3001).
I would like to be able to communicate with both of them from a single domain.
Ex :
https://example.com/ => redirect to the front-end
https://example.com/a-specific-page => redirect to a specific page of the front-end
https://api.example.com/ => redirect to the backend API
https://api.example.com/login => redirect to the login part of the API
How can I do this ?
I've already tried some things :
redirect subdomain from my provider (ovh.com) => this is not the way
create a third nodejs server at the root on port 80 and redirect manually, but I don't think it's a good way because I have to consider all possibilities of domain name (www.mydomain.com / mydomain.com / http:/ etc...) and used concurrently to run all together
I don't really want to put frontend and backend in the same running server (same port)
I'm quite new in mastering servers so I don't kown nothing, sorry.
Thanks for the help.
PS: I'm french, so sorry for the bad English :)
Hello since i dont have that much information i will stay general.
What you want is a reverse proxy. You can use http-proxy-middleware: https://www.npmjs.com/package/http-proxy-middleware.
Let's say you run your frontend on http://example.com:3000 and your backend on http://example.com:3001.
Now lets say you want http://example.com:3001/42-is-the-answer to point to http://example.com:3000 (You can add a path if you want).
The only thing to do would be to use a proxy on the server instance of example.com:3001 like so:
const proxy = require("http-proxy-middleware");
const app = express();
....
app.use( proxy("/42-is-the-answer", {
target: "http://example.com:3000/"
}))
Now if you access http://example.com:3001/42-is-the-answer, the request will be proxied to http://example.com:3000.
I hope this helps.

Set Base URL for Preact CLI

Using Preact CLI is it possible to set the path where the app will be hosted outside of the root directory?
For instance hosting the app at http://mywebsite.com/relativepath/index.html
You have several problems to solve:
1. Get Webpack to output the correct paths in your html
This is done via creating a preact.config.js in your root folder, and put the following in there
export default (config) => {
config.output.publicPath = '/relativepath/';
};
2. Set your navigation and assets links in your app
The best way to solve it in my opinion is to use a global variable which you can be used in your app. So again, edit the preact.config.js to the following:
export default (config, env, helpers) => {
config.output.publicPath = '/relativepath/';
// use the public path in your app as 'process.env.PUBLIC_PATH'
config.plugins.push(
new helpers.webpack.DefinePlugin({
'process.env.PUBLIC_PATH': JSON.stringify(config.output.publicPath || '/')
})
);
};
3. Routing
When using your preact app, it should be no problem to navigate. However, if you try to load a fresh URL e.g. www.myserver.com/relativepath/mything/9, the server doesn't know that it should load your single page app living at www.myserver.com/relativepath/index.html
You have two options:
a) Server-side routing
Make sure your all the requests to relativepath (including e.g. relativepath/mything/9) will be rewritten to your app's relativepath/index.html (in case of using Apache).
Then your Javascript can process the routes, e.g. preact-router
b) Client-side routing (recommended)
The easier option for enabling reloading of URLs is to use hash urls, thereby avoid going through the server when loading a URL.
Your URLs will look something like www.myserver.com/relativepath/#/mything/9
The server ignores the part after # and only loads (hopefully) /relativepath/index.html
You can use e.g. the preact-router with Hash History to avoid server-side routing, read about it here https://github.com/developit/preact-router#custom-history
I'm proxying from http-proxy-middleware to the preact-cli dev server and these settings worked for me in preact.config.js
export default (config, env, helpers) => {
config.output.publicPath = '/relativepath';
config.devServer.devMiddleware.publicPath = "/relativepath";
};

Static sites with nginx and express.js - Authentification

My plan
In my app, I want to separate the backend from the frontend. I have multiple static sites with vue.js accessing an api provided by an express server. All static files should be served by nginx.
So for now my nginx config file looks like this:
http {
...
upstream backend {
server localhost:3000;
keepalive 64;
}
...
server {
...
location /api {
...
proxy_pass http://backend;
}
}
}
So all request to /api are handled by express running at port 3000. Users can login through the frontend that is accessing the backend api.
Now to the problem:
I have some sites (e.g. /dash) that are also static but should only be accessible for users that are authenticated (authentication is handled by express session) and with a specific user role (e.g. editor).
A user who is not an editor should get a error 403 when accessing /dash while for the others, /dash should be served by nginx.
I hope I was clear enough, it is not easy to express my problem properly. I appreciate any help and advice, maybe my approach is not a good idea or is a bad practice.
Edit
Solution can be found in comments of the right answer.
For starters, authorization to some static files should be handled in the backend-server and not in nginx. Nginx is just a proxy, and not a handler for authorization. Maybe check out passport if you're using express.
Secondly, I think you have the wrong idea about static files. A tip would be to compile them to make them smaller(check out http://nginx.org/en/docs/http/ngx_http_gzip_module.html). But that's how far nginx will handle your static files.

How to bind a domain name to expressjs application

How to bind a domain name to expressjs application.My application is running on servername:1001
I want to bind it to www.domainname.com. How can I do this in the application.
I'm searching for the same answer.
I have just been using app.use('/', router) with a processor that then checks the domain off the req object.
router.get('*', (req, res, next) => {
let path = req.path.replace(/^\//g,'').replace(/\/$/g,'');
let domain = req.headers.host.split(':')[0];
domain = domain.replace(/^www\./g,'');
});
This is the closest thing I've been able to come with to actually using express routes per domain. On my own, 4 years ago.
Now there seems to be this VHOST module:
http://expressjs.com/en/resources/middleware/vhost.html
-Robert
Your DNS record you should use CNAME. As a value you should use the domain your hosting provider gave you ex. myapp.herokuapp.com(which on heroku side point to servername:1001).
If you are using hosting like heroku, you should setup to accept traffic for your application for that specific domain. That last configuration is being made on heroku management site.

http basic authentication with different rights

I am in middle of a development, and havent so far created user authentication in my node.js application,however I have an admin back-end where I do not want the users provided with the username and password.
I am looking for a way to implement basic http authentication but depending on the credentials provided, they can or can not go to different areas of site, in short: I want different credentials for admin page.
Any help will be appreciated.
Thanks and regards,
Babar
As I understand it you want two different types of testers. One to test frontend, but not affect backend and one that also affects backend.
I would actually run two instances of Node and point the testers to two different urls.
And in your routes you check the environment, giving fake responses to "testers1" and actual backend respones to "testers2".
Like:
NODE_ENV=simulated node server
function (req, res) {
if (process.env.NODE_ENV === 'simulated') {
// Give fake response
} else {
// Get from backend
}
}
Use multiple location blocks and separate access files or something like this:
location /test/ {
auth_basic "Test";
auth_basic_user_file /access.txt;
root '/webroot/$remote_user';
}

Resources