How to implement REST API Versioning with nodejs + NGINX? - node.js

From past few days, I m working on How to implement API versioning with help of NGINX.
At an application level, I m able to implement But this required 2 Diff controller, 2 diff route, 2 diff model etc.. I don't want to do that.
I want two different projects like v1 and v2. Using NGINX, If my URL contain v1 then it's point to v1 project and if URL contain v2 then it will Point to v2 project something like that.
I know using NGINX ALIAS or ROOT we able to do that but I don't know how?

In fact, we are talking about how to configure nginx as a reverse proxy. And do proxies for different projects, depending on the content of URL.
In your case, you need to:
Configure the sail-projects at different ports. For example:
for API.V1: sails.config.port -> 3010
for API.V2: sails.config.port -> 3020
Add to nginx configuration (nginx.conf) two upstream (for example for nginx and api-projects located on the same server).
Add to nginx configuration (nginx.conf inside server block) two locations for different api's.
Nginx configuration might look like this:
upstream api_v1 {
server 127.0.0.1:3010;
keepalive 64;
}
upstream api_v2 {
server 127.0.0.1:3020;
keepalive 64;
}
server {
listen 80;
server_name example.com;
location /api/v1 {
proxy_pass http://api_v1;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
}
location /api/v2 {
proxy_pass http://api_v2;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
}
}

Related

How do you change the MSAL Reply URL when the Azure APP Service is behind a reverse proxy like NGINX?

I will skip the usual rant on time spent, frustration, MS is stupid, etc.
I have tried to be as complete as possible
We have 5 Azure App Services, 3 aspdotnet core 5.0 and 2 Blazor Server apps we are using Azure AD B2B.
We had the first two or three working on Front Door and then discovered it does not support SignalR (websockets). Wait, I promised not to rant.
We switched to NGINX.
Below is the basic configuration (all https). It is verbose and I checked each one as I wrote this, hoping to find an error.
app1.azurewebsites.net
app2.azurewebsites.net
app3.azurewebsites.net
app4.azurewebsites.net
app5.azurewebsites.net
We need it to work like this
domain.com/ - app1
domain.com/app2
domain.com/app3
domain.com/app4
domain.com/app5
The Redirect URIs in AD, the application configuration overrides, and appsettings.config are set to
domain.com/signin-oidc
domain.com/app2/signin-oidc
domain.com/app3/signin-oidc
domain.com/app4/signin-oidc
domain.com/app5/signin-oidc
My current NGNIX config is
server_name domain.com
listen 80;
listen [::]:80;
listen 443 ssl;
ssl_certificate /etc/nginx/ssl/mycert.cert;
ssl_certificate_key /etc/nginx/ssl/mycert.prv;
location /app2 {
proxy_pass https://app2.azurewebsites.net/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header X-Real-Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location / {
proxy_pass https://app1.azurewebsites.net/;
proxy_redirect off;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
The app service all have this code.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto |
ForwardedHeaders.XForwardedHost;
});```
When I try domain.com in the browser I get this error
**AADSTS50011: The reply URL specified in the request does not match the reply URLs configured for the application: '{ClientId Guid}'.**
When I inspect the request it looks like this
https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id={ClientId Guid}&redirect_uri=https://app1.azurewebsites.net/signin-oidc ...
This is true for all of the apps
I am at a loss as how to solve this. MS support was no help even in a made up non-NGINX scenario.
I hired a NGINX "expert" who got nowhere.
I have a call scheduled EOW with OKTA, who "believe" they have a solution.
None of this is optimal and has wrecked hours of CI/CD work.
Has anyone made this work? If so how?
TIA
G
I believe this is a workaround but have you tried to change the AD's Redirect URIs to *.azurewebsites.net instead of domain.com/appN/signin-oidc?

How do i configure nginx (and strapis) to correctly serve two strapi instances on the same server?

i want to host two small websites, both made with strapi backend and react frontend, on my server which is a digital ocean droplet.
I already configured nginx in order to work for one of the websites and everything is working correctly. I can access strapi from site1.com/dashboard and my queries point to site1.com/api/graphql. I followed some tutorials for that.
Here are the nginx files i added:
/etc/nginx/sites-available/site1.com:
server {
listen 80;
listen [::]:80;
root /var/www/site1.com/react;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
server_name site1.com www.site1.com;
location /api/ {
rewrite ^/api/(.*)$ /$1 break;
proxy_pass http://strapi;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_pass_request_headers on;
}
location /dashboard {
proxy_pass http://strapi/dashboard;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_pass_request_headers on;
}
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ /index.html;
}
}
file /etc/nginx/conf.d/upstream.conf:
upstream strapi {
server 127.0.0.1:1337;
}
What i now want to do is to deploy another website to the same server and configure nginx to serve it as well (on another domain, for example site2.com).
So i added the nginx virtual server file for the second website, copying the first one and changing the domain name and root directory.
The site 2 frontend is now working correctly and accessible on its domain.
However when i start the site 2 strapi instance it says the port 1337 is already in use (obviously, it is used by site 1 strapi instance that is running with pm2). So i changed the port in strapi config to be 1338 (is it ok?) but now i don't know what do to in nginx in order to serve the two different strapi instances on different domains.
The hostname you are using for the proxy_pass directive is the upstream name you defined in the separate config file. This is basically an indirection to one or more real backends. In your case that's the application running on port 1337 on the same machine. It could also be a list of external domains where nginx takes care to distribute the load to.
Your approach with additional virtual hosts already looks good. The frontend that already "works" under site2 is probably the old instance served under the new domain if your proxy_pass directive still points to http://strapi for site2 (which probably still resolves to `localhost:1337).
As you already mentioned, a second instance of the backend needs to run on a different port. The port number you use is not really important as you will control this with your upstream configuration. Just make sure to not use a port number below 1024 (which requires root permissions), don't conflict with other processes on the system (you will notice) and as best practice, don't use port numbers that are default for some other protocols (maybe check this list).
To fix your setup, just define a second upstream like the first one but pointing to the new url e.g. localhost:1338 and then reference this new name in the proxy_pass directive of site2.
Technically, with just one backend per upstream, you could also skip the upstream part completely and reference the URL directly in the proxy_pass directives, but using a shorthand name can also support readability of your configuration.

Use Heroku server url at nginx.conf.erb for load balancing

I have 2 server:
Server 1 is for loading balance with Nginx - https://server1.herokuapp.com/
Server 2 is for acting RESTful APIs. - https://server2.herokuapp.com/
Here my configuration of nginx.conf.erb at Server 1: https://gist.github.com/ntvinh11586/5b6fde3e804482aa400f3f7faca3d65f
When I try call https://server1.herokuapp.com/, instead of return data from https://server2.herokuapp.com/, I reach a 400 - Bad request. I don't know somewhere in my nginx.conf.erb wrong or I need implement nginx in server 2.
Try to research some resources but I found almost these tutorials configuring in localhost instead of specific hosts like heroku.
So what should I do to make my work successfully?
You need to configure your app as follows -
#upstream nodebeats {
# server server2.herokuapp.com;
# }
server {
listen <%= ENV['PORT'] %>;
server_name herokuapp.com;
root "/app/";
large_client_header_buffers 4 32k;
location / {
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_set_header Connection "";
proxy_http_version 1.1;
proxy_pass http://localhost:<node-app-port>;
}
My two cents.
Comment out the upstream. Work with a single server server1.herokuapp.com, get it working with the above implementation, and then you can accomplish on adding the server2.hreokuapp.com to load balance.

Nginx + NodeJs - Limit port access to a server name

i’m new to the javascript world and im trying to publish online a small react app that i‘ve done for tests.
So, first i installed nodejs in my server that already has nginx. Then expressjs, configure it and made a nginx .conf file that uses proxy_reverse to access port 8080 (chosen for nodejs). When i access the server name of that .conf file, without the port, the page it’s shown correctly.
The problem is, if i access another server name configured in my server and add the 8080 port at the end, nginx shows me my nodejs app, even with a server name different from the one configured in proxy_reverse.
Is there any way to limit access to that specific port to one specific server name and return a error everywhere else?
My nginx conf file:
server {
listen 80;
server_name react.mydomain.com;
access_log /var/log/nginx/react.access.log;
error_log /var/log/nginx/react.error.log error;
location / {
proxy_pass https://localhost:8080;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
# Enables WS support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_redirect off;
}
}
Thanks

Amazon Elastic beanstalk : Use nginx/apache to forward subdomains to subfolders

I've created my node.js app on ebs with two subrouters 'foo' and 'bar', currently accessible via 'example.com/foo' and 'example.com/bar'.
I'd like the reverse proxy of ebs to forward the subdomains "foo.example.com" and "bar.example.com" to these subfolders...
i.e. "foo.example.com/xxx" to "example.com/foo/xxx"
"bar.example.com/yyy" to "example.com/bar/yyy" etc.
I know how to configure nginx to do this, but I can't figure out to access the nginx config files on EBS...
Someone asked exactly the same thing over a year ago, but it seems EBS has developped a good deal since... would just like to know if this sort of thing is now doable.
you can use Configuration File to customize your nginx configuration.
Create an .ebextensions directory in the top-level of your source bundle.
Create a configuration file, /your_app/.ebextensions/custom.config. Type the following inside the configuration file to configure forward settings. (I have created a gist)
files:
"/etc/nginx/conf.d/custom.conf" :
content: |
server {
listen 8080;
server_name foo.chief-motp.com;
location / {
proxy_pass http://nodejs/foo/;
proxy_set_header Connection "";
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /public {
alias /var/app/current/public;
}
}
server {
listen 8080;
server_name bar.chief-motp.com;
location / {
proxy_pass http://nodejs/bar/;
proxy_set_header Connection "";
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /public {
alias /var/app/current/public;
}
}
Another methodology to customize Elastic Beanstalk EC2 instances is using Custom AMI. For more information, you can refer my post.

Resources