nginx proxy_pass for get request api call with parameters - api

I have simple flask rest api that fetches data from database and gives result to user in json file. flask server gets parameters from html input fileds upon submit and these parameters are used to fetch data from database. It is working fine with flask inbuilt WSGI server. I wanted to deploy in production with nginx as my web server and gunicorn as application server. When I run docker container and access the root url, i can get html form for the user to input parameters. When I click on submit, another api resource call gets invoked, but I get either 'URL not found' or 'internal server error'. This surely problem with nginx location configuration for my get request api call with parameters in URL. Please help me how to configure nginx proxy_pass URL for this kind of request.
My browser request URL look something like this when I submit form.
http://IP address/api/v1/service?key=12345&name=abc&id=1234
HTML (form.html)
<form name="device" action="/api/v1/service">
Python view functions
#app.route('/')
def my_form():
return render_template('form.html')
#app.route('/api/v1/service', methods=['GET'])
def my_form_get():
..............
.............
nginx server
server {
listen 80;
location / {
proxy_pass http://localhost:5000/;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /api/v1/service {
proxy_pass http://localhost:5000/api/v1/service;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
Gunicorn configuration
[program:gunicorn]
command=/usr/bin/gunicorn run:app -b localhost:5000
directory=/deploy/app

You can use the following nginx configuration:
upstream v1service {
server v1servicecontainer:8080;
}
server {
listen 80;
location ~ ^/api/v1/service(.*)$ {
resolver 127.0.0.1;
proxy_pass http://v1service/api/$1$is_args$args;
proxy_redirect off;
proxy_set_header 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-Host $server_name;
}

Related

Nginx not redirecting on named route

I'm trying to setup a reverse proxy to a sentry relay using Nginx. Config file as follows:
events {
worker_connections 768;
}
http {
server {
listen 0.0.0.0:80;
location /sentry-relay {
proxy_pass http://127.0.0.1:3001;
proxy_redirect off;
proxy_set_header 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-Host $server_name;
}
}
}
Browsing directly to the relay server on port 3001 works fine:
However using the location path set in Nginx fails:
I've also put the redirect onto the default path: location / and it works fine. Why won't this custom path redirect properly?
I worked it out.
Nginx will append the location prefix to the proxy server request unless this prefix is replaced.
Thus to fix I changed:
proxy_pass http://127.0.0.1:3001;
to
proxy_pass http://127.0.0.1:3001/;
The extra slash is used to replace the sentry-relay path.

how to proxy to my domain with port from request urls that start with api?

I have a loopback 3 set up listening on the port 3000. And my front end app is built with Vue JS. ( I uploaded dist files to the server). Whenever I make an api call (https://example.com/api/xxx), I need to proxy to (https://example.com:3000/api/xxx) in order to avoid cors issues.
How do I resolve this?
FYI, the loopback and vueJS are hosted on the same web server (apache, centos8)
Use NGINX Reverse Proxy
https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/
http://localhost:5000 - points to your Vue.js app
http: //localhost:3000 - points to your REST API app
server {
listen 80;
server_name example.org;
location / {
proxy_pass http://localhost:5000;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
}
location ^ ~/api {
proxy_pass http: //localhost:3000;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
}
}

troubleshooting application behind nginx reverse proxy, as POST/PUT requests are replied with Error 400 (Bad Request)

I'm trying to host my Angular/ASP.net core 3.1 application on linux for the first time.
Nginx stands on the port 80 and serves the static files and acts as a reverse proxy for the api part which will be passed to the .NET/kestrel server.
The problem is that I systematically get a 400 status code error (Bad Request) on any web API request containing a body, like POST & PUT, but GET is ok.
I added some logs through a middleware, just to see if I can get the requests. Basically, something like:
app.Use(async (context, next) => {
context.Request.EnableBuffering();
string reqBody;
using (var reader = new StreamReader(context.Request.Body))
{
reqBody = await reader.ReadToEndAsync();
context.Request.Body.Seek(0, SeekOrigin.Begin);
ms_oLogger.Debug($"Incoming request: METHOD={context.Request.Method} PATH={context.Request.Path} BODY=\"{reqBody}\"");
}
await next();
});
This just loggs stuff for GET requests, but nothing appears for the problematic PUT/POST requests... Can I conclude that this is only a nginx problem?
I also enabled the logs on nginx for the given "/api" location, but I can not tell what happens... How can I know which tier has generated the 400 status code?
EDIT1: I started a blank new project just with a poor Web API project containing one GET and one POST method just to check if there was something wrong with my application, but I still get the problem.
So I set up a new ubuntu server (this time, ubuntu server instead of desktop version) and now it works!!!
I compared configuration etc... but could not figure out what was wrong!....
But my initial question is still valid: how can I troubleshoot where the problem comes from?
EDIT2: This is my default.conf:
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name _;
location / {
try_files $uri $uri/ =404;
}
location /fusion {
root /opt/fichet/WebUI/NgApp;
}
location /fusion/api {
proxy_pass http://localhost:5000/api;
error_log /var/log/nginx/fusion_error_logs.log debug;
access_log /var/log/nginx/fusion_access.log;
proxy_http_version 1.1;
proxy_cache_bypass $http_upgrade;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header 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;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
}
}
It seems that no firewall is enabled ("sudo ufw status verbose" tells us that it is "inactive")
Remove these lines from your nginx config.
proxy_cache_bypass $http_upgrade;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
These headers are used for WebSocket connections, and shouldn't be present for non-websocket requests. My guess is your upstream server doesn't mind them for GET requests but does for POST/PUT, for some reason.
If you are not using websockets, you can leave them removed.
If you are using websockets, you need nginx to add or not these headers based on whether the requests is websockets or not. Something like this should work:
http {
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
...
location /fusion/api {
proxy_pass ...
...
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
See here for more info.

Loadbalancing with Nginx error not redirecting properly

I was able to get the load balancer to work only on inception. It seems that when I do any clicks on the page, it renders http://backend , and not the actual web address.
here is my config on the downstream
upstream backend {
server unix:///var/www/my_app/shared/tmp/sockets/puma.sock;
}
server {
listen 80;
location / {
proxy_pass http://backend;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

Customize URL location for loadbalancing nginx

I am new to nginx.
I am having WCF Rest Service listening in the following url,
127.0.0.1:portHere/Service1.svc/RemainingRestURLTemplate.
Here is the config I am having.
http {
upstream servers_customserver {
server 127.0.0.1:62133;
server 127.0.0.1:62134;
server 127.0.0.1:62135;
}
server {
listen 8090;
server_name localhost;
location /two/ {
proxy_set_header 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-Host #server_name;
proxy_pass http://servers_customserver;
}
}
}
Upon entering localhost:8090/two/, I thought the upstream will work,but the browser reports problem, as in the image.
But the browser works fine when I have removed the "/two/" from my location, as below.
So, how to make my upstream to work, only when the user typed the url ends with "/two/".
Could some one share some input on it.
Thx in advance.
Finally after some hrs, found that trailing slash did the work.
proxy_pass http://servers_customserver/ works instead of proxy_pass http://servers_customserver Correct me if am wrong.
Thx.