Nginx rewrite rule for Node.js - node.js

I'm setting up Nginx as a reverse proxy for a Node.JS application.
Node app listens on localhost:3003 and proxy is set up like this:
location /otfb {
proxy_pass http://127.0.0.1:3003;
#...
}
Now the problem is that if I access server like this:
http://server.xyz/otfb/someresource
then it is passed to Node.JS as
http://localhost:3003/otfb/someresource
But correct will be
http://localhost:3003/someresource
Show how to set up rewrite rule so that otfb will be removed by Nginx before request is passed to Node.JS

It turned out that rewrite isn't needed at all
Working configuration:
location /otfb/ {
proxy_pass http://127.0.0.1:3003/;
#...
}
Just slashes was missing at the end of URIs

Related

How to set proxy pass for react app on nginx?

My react app has got different routes to consume different functionalities
e.x.
localhost:3000,
localhost:3000/Dashboard,
localhost:3000/Hub,
localhost:3000/Person
etc....
I wanted to configure the react app routes in the nginx in the production environment. What I have actually done so far in the nginx configuration at production env is,
server_name api.vesta-project.net;
location /vqcc {
proxy_pass http://localhost:3000/;
}
My problem here is with the current settings, the homepage works well when I say "api.vesta-project.net/vqcc". Whereas, when I click a button that navigates to /Dashboard. I get 404 error as it does not append "vqcc" to the path in the react app internally thus it becomes like api.vesta-project.net/Dashboard" when inspecting the request which is wrong per nginx conf. So I need a solution whenever the client make a request, it should append "vqcc" to the path so that it will become a valid url as per nginx routes.
e.x when client request for api.vesta-project.net/Dashboard, it should become
api.vesta-project.net/vqcc/Dashboard
Pls help me if I can handle this at nginx or package.json without being changing any routes in the react app internally
You can try rewriting the uri in catch-all location.
location / {
rewrite /(.*) /vqcc/$1;
}
location /vqcc{
proxy_pass http://localhost:3000/;
}

nginx responding "301 moved permanently"

Consider the following nginx config file:
server {
listen 443;
ssl on;
ssl_certificate /etc/tls/cert.pem;
ssl_certificate_key /etc/tls/key.pem;
location / {
proxy_pass http://api.default.svc.cluster.local;
}
}
All incoming TCP requests on 443 should redirect to my server running on api.default.svc.cluster.local:80 (which is a node REST-Api btw). This works fine, I can curl https://<nginx-IP>/ nginx and get a correct response, as expected.
Now, I'd like to change the location from / to /api, so I can fire a curl https://<nginx-IP>/api in order to get the same response as before.
1. Attempt
So I change the location line in the config to:
location /api {
Unfortunately this won't work, instead I get an error Cannot GET /api which is a node error, so obviously it gets routed to the api but something's still smelly.
2. Attempt
It seems as the trailing slash in an URI is required so I added it to the location:
location /api/ {
Now something changed. I won't get the same error as before, instead I get an "301 moved permanently". How can I fix my nginx config file?
Additional information regarding the environment
I'm using a kubernetes deployment that deploys the nginx reverse proxy incl. the config introduced. I then expose nginx using a kubernetes service. Also, I tried using kubernetes ingress to deal with this situation, using the same routes, however, the ingress service would respond with a default backend - 404 message.
As mentioned in the question, trailing slashes in URIs are important. I fixed this in the location, however, I didn't add it to the URI I pass using proxy_pass.
As for the nginx proxy I got it to work using the following config:
server {
listen 443;
ssl on;
ssl_certificate /etc/tls/cert.pem;
ssl_certificate_key /etc/tls/key.pem;
location /api/ {
proxy_pass http://api.default.svc.cluster.local/;
}
}
Concerning the ingress solution, I was not able to get it to work by adding the missing trailing slash to the path. The service is specified due its name and therefore no trailing slash can be added (i.e. it would result in an error).

nginx proxy to remote node.js express app in subdirectory

I am completely stuck with a situation where I want to have several node applications on one server. I get this working fine by having the applications running on different ports. I can access the applications by putting in the ip address with port.
I would like to proxy the applications from my nginx server by using different sub-directories like so:
my.domain
location /app1 {
proxy_pass http://10.131.6.181:3001;
}
location /app2 {
proxy_pass http://10.131.6.181:3002;
}
Doing this I had to move the all the express routes to /app1 for application1. This works but now I am stuck with the static files.
I can now access the application with http://10.131.6.181:3001/app1 which is great, but via http://my.domain/app1 the static files are not loaded.
The static files can be accessed directly http://10.131.6.181:3001/css but not via the proxy http://my.domain/css
Ideally I would like to have the applications on different ports without the sub-directory in the express routes but only sub-directories in the proxy. I tried to put my head through the wall for the last 5 hours but didn't achieve anything.
Now I would happy if can at least get the static files via the nginx proxy.
An updated answer for anyone who needs:
instead of
location /app1 {
proxy_pass http://10.131.6.181:3001/app1;
}
use
location /app1/ {
proxy_pass http://10.131.6.181:3001/;
}
or if on local
location /app1/ {
proxy_pass http://localhost:3000/;
}
This is the correct way and this way you will not need to modify express. Express will receive only the part after /app1/
I finally worked it out after a google surge.
I added the directories to the nginx proxy_pass
my.domain
location /app1 {
proxy_pass http://10.131.6.181:3001/app1;
}
location /app2 {
proxy_pass http://10.131.6.181:3002/app2;
}
And I had to change the express applications to use the subdirectory
app.use('/app1', express.static(path.join(__dirname, 'public')));
app.use('/app1'', require('./routes'));
In the router I had to prefix all the redirects.
router.get('/logout', function (req, res) {
req.logout();
res.redirect('/app1/login');
});
The static files are called like so from html
<link rel="stylesheet" href="/app1/css/style.css"/>
A bit of a pain to change all the redirects and static url. I am sure there is a smarter way by setting a global variable in my node-express app. If anybody knows an easier way please post...

Passing parameters to nginx url

How to pass parameters in nginx url. When I hit http://127.0.0.1:1000/samp/test1/result?num1=10&num2=30, it should redirect me to http://127.0.0.1:80/samp/test1/result?num1=10&num2=30. Is this possible? Below is my nginx config file.
upstream apache {
server 127.0.0.1:1000;
}
server {
listen 80;
server_name 127.0.0.1;
location / {
#root html;
#index index.html index.htm;
#return 503;
proxy_pass http://apache;
}
}
I think what you want to do is possibe, but you'd have to make that configuration change on the apache end of things.
If 'apache' handles a request coming into port 1000 directly, it will see a URI like this:
http://127.0.0.1:1000/samp/test1/result?num1=10&num2=30
However, if it is sent through nginx, it will look more like this:
http://apache/samp/test1/result?num1=10&num2=30
So, you could check the incoming URL for :1000 and then rewrite the request on the apache side to go to port 80 instead ( which is the default, so you don't need :80 - you can just leave the port unspecified entirely.
If the backend really is apache, you can use a rewrite rule there to handle the rewriting.
However, if you're not already on port 80, you're not connecting to nginx - so nginx can't rewrite this for you.
Hope it makes sense!
Here's how I tested:
Apache side I used a quick sinatra (ruby) app to print out the full URI of the request it sees:
require 'sinatra'
set :bind, "0.0.0.0"
set :port, 1025
get "/*" do
"<p>Hello from \"apache\"! You've just requested:
<code>#{request.url}</code></p>
"
end
Then nginx is configured thusly:
upstream apache {
server 192.168.70.1:1025;
}
server {
server_name localhost;
location / {
proxy_pass http://apache;
}
}
Note I used port 1025, because port 1000 is a privileged port.
I used curl to generate the requests to test:
$ curl 'http://192.168.70.1:1025/samp/test1/result?num1=10&num2=30'
<p>Hello from "apache"! You've just requested:
<code>http://192.168.70.1:1025/samp/test1/result?num1=10&num2=30</code></p>
$curl 'http://127.0.0.1:80/samp/test1/result?num1=10&num2=30'
<p>Hello from "apache"! You've just requested:
<code>http://apache/samp/test1/result?num1=10&num2=30</code></p>
If I wanted to do the redirect you're describing, I could match with a regular expression of IPV4 address and port and redirect as such:
get "/*" do
if request.url =~ %r|^http://([0-9]{1,3}\.){3}[0-9]{1,3}:1025/|
redirect "http://localhost:80/#{request.fullpath}"
else
"<p>Hello from \"apache\"! Tou've just requested:
<code>#{request.url}</code></p>
"
end
end
Now I tell curl to follow redirects (-L) and we see it redirect me over to the "correct" route.
$ curl -L 'http://192.168.70.1:1025/samp/test1/result?num1=10&num2=30'
<p>Hello from "apache"! Tou've just requested:
<code>http://apache/samp/test1/result?num1=10&num2=30</code></p>
I know it's not the language you're using, but I hope it iwll help you get started.

Redirect from node server to nginx server

I have below nginx conf file
upstream entry {
server 127.0.0.1:3001;
}
server {
listen 80;
server_name 127.0.0.1;
location / {
proxy_pass http://entry/;
}
Whenever I hit http://127.0.0.1:80/, it will be redirected to 127.0.0.1:3001. In the same way if I hit http://127.0.0.1:3001/ it should be redirected to nginx server.
Any help on this will be really helpful.
If I am getting it correct you want http://127.0.0.1:3001/ (node http server) to redirect to http://127.0.0.1:80/ (nginx), which in turn will redirect to http://127.0.0.1:3001/ (node http server). Why on earth you want to do that? You can use node proxy module to do that if you want to fall inside a infinite for loop.
But generally, sane people will will use nginx as reverse proxy (80->3001). And block port 3001 for any outside communication through firewall.

Resources