How to track bytes sent in Nginx - nginx

I'm using NGinx as a large file content delivery server, I need to track how many bytes are sent to the client when they download a file. Then with some ID deduct the bandwidth from their account. Here is my Nginx config, but it doesnt seem to work. On my test server running on 8899 I dont get any hit no matter what.
location /test {
try_files $uri #afterdownload;
alias /home/ubuntu/test/;
post_action #afterdownload;
}
location #afterdownload {
proxy_pass http://localhost:8899/?FileName=$uri&ClientIP=$remote_addr&body_bytes_sent=$body_bytes_sent&status=$request_completion;
internal;
}

You can use this module
https://github.com/Lax/ngx_http_accounting_module
but I think you need to make customization to fit your case outside nginx along with this module.

Related

Can a response from an http request alter the base address in the next client request?

I have an octoprint server running at http://192.168.1.205. I also have an nginx server hosting myDomain. I want to be able to use the nginx server to pass on a request for http://myDomain/octo to http://192.168.1.205 using a reverse proxy. Here is my nginx code...
server {
server_name myDomain;
location /octo/ {
rewrite ^/octo/(.*) /$1 break; #strip /octo from url
proxy_pass http://192.168.1.205;
}
}
The first http://myDomain/octo request is passed on to http://192.168.1.205 correctly. But after the first response the code in the client makes another request to http://myDomain/moreUri. Since this uri doesn't have /octo nginx doesn't know to send it to http://192.168.1.205/moreUri. Is there a way to have nginx change something in the first response so that the client then makes following requests to http://myDomain/octo/moreUri?
I was able to accomplish this for a case where the octoprint server responded with a redirect. I used ...
proxy_redirect http://192.168.1.205/ http://myDomain/octo/;
and it worked. But that only works on redirects and the following requests were wrong again.
Is there a way to have nginx change something in the first response so
that the client then makes following requests to
http://myDomain/octo/moreUri?
I am not aware that this is possible.
What about to adjust the nginx configuration accordingly ? using location / to process all requests within that block and add an additional redirect directive to address the "Since this uri doesn't have /octo nginx doesn't know to send it to http://192.168.1.205/moreUri" should do the trick.
server {
server_name myDomain;
location / {
rewrite ^/octo/(.*) /$1 break; #strip /octo from url
rewrite ^/(.*)/(.*) /octo/$2 break; #rewrite /moreURI to /octo/moreURI
proxy_pass http://192.168.1.205;
}
}
No matter if the above nginx reconfiguration fixes your issue, i assume the root cause why you need to configure the nginx as reverse proxy in this way might be a misconfigured (or not optimally configured) application. Check the config file if it is possible to configure the applications base path. If so, set it to /octo/ (so the application itself prepends /octo/ to all the links it presents to the user and all requests to the backend automatically) and adjust the rewrite rules accordingly.

Download files in remote server using reverse proxy Nginx

I have a server running with Nginx reverse proxy.
We have our application running in another server, which is served using this Nginx proxy. Below is the configuration I have used and its working fine.
location / {
rewrite ^/(.*) /$1 break;
proxy_pass http://10.0.0.121:8000;
}
I would need to download a pdf file in the application machine (10.0.0.121) , which is under /home/ubuntu/app/pdf/data-2021-03-25.pdf.
How could I make the file in application machine downloadable from the proxy server, please help.
Thanks in Advance.
I would simply install another nginx instance on 10.0.0.121 and configure it like this. NON-PROD READY!
server {
listen 8080;
server_name ...;
root /home/ubuntu/app/pdf;
location = /data-2021-03-25.pdf {
try_files $uri $uri/ =404;
}
server {
listen 8090;
location / {
proxy_pass http://localhost:8080;
}
}
}
Not tested but this server will handling the request serving the file. Then you could just use proxy_pass on the other server to proxy the request.
But beside from this option you can use a python, perl, php, java, nodejs, assembly or what ever programming language you want to use to open a http port and serve the file on an incoming request. Its really your choice.
just make sure if you're going for the proxy solution you are sanitizing the requests on your proxy. For example. With a small change in the setup above you could cheat and get any other files from your home/app directory by sending an request like curl -v localhost:8090/pdf/../other/file. So make sure you are using the root(/home/ubuntu/app/pdf/) directive and set a location matching the pdf-file on the proxy-server as well.
That worked in my demo app.

Nginx proxy redirect without changing url

I have a nginx (:80) and an upstream server (:8080) running on my machine.
I want to proxy all requests to /assets/(*.?) to upstream's /upstream/$1 location.
The upstream server redirects (302) /upstream/file_id to the /real/file/location.ext
Here is my code:
location /assets/ {
rewrite ^/assets/(.*) /upstream/$1 break;
proxy_pass http://127.0.0.1:8000;
}
This seems to work, but on the client side I get the redirected location:
http://myserver.com/real/file/location.ext
I kinda want to hide it so that it stays:
http://myserver.com/assets/file_id
The idea behind this is to make the upstream server find the real file's location, but let the nginx serve the file without giving away its real location. Is this even possible?
first you're using 8000 in proxy_pass, but you're mentioning your port is 8080.
Second, remove the rewrite line should do the trick, because youre actually using the rewrite rule here and never get to the proxy_pass line. Something like the following should work:
location /assets/ {
include proxy_params;
proxy_pass http://127.0.0.1:8080;
}
There are also proxy_rewrite and proxy_redirect commands which might help you in getting this upstream-redirect handled internally by nginx.
Hope that helps!

NGINX Location troubles

I have django and flask applications running on the same machine through different ports:
Django runs on server:8088
Flask runs on server:666
In NGINX.conf I have the following code:
location / {
proxy_pass http://127.0.0.1:8088;
}
location ^/server2 {
proxy_pass http://127.0.0.1:666;
}
Django has been running for over a year successfully with this set up, where as flask is a new addition. Any time I try to access one of the Flask urls I either get a "this url does not exist on this server" error, or on occasion a 500 error (when i've been fiddling).
If I write location information for a specific flask url like this:
location /server2/splash {
proxy_pass http://127.0.0.1:666/splash;
}
It works, but I obviously don't want to write individual location information for each and every URL in the flask application.
I've gone through many of the existing Nginx location posts on stackoverflow but I've not been able to get it working. Any ideas?
Thanks!
EDIT
this is an example of what I'm trying to achieve, but rather than an individual mapping for each URL, I want a single mapping that covers all URLs:
location /server2{
proxy_pass http://127.0.0.1:666/splash;
}
location /server2/split {
proxy_pass http://127.0.0.1:666/split;
}
location /server2/export {
proxy_pass http://127.0.0.1:666/export;
}
location /server2/import {
proxy_pass http://127.0.0.1:666/import;
}
Why do you use the ^ sign? Just remove it I think it will work:
location /server2 {
proxy_pass http://127.0.0.1:666;
}
Note that when you use location /server2 the server2 is still being passed to your flask application.
In this case Nginx is doing the following:
server.com/server2 => http://127.0.0.1:666/server2
server.com/server2/splash => http://127.0.0.1:666/server2/splash
In this case location is not doing a rewrite. Always check /var/log/nginx (or wherever your logs are located) to check the requests done by the browser and what Nginx looks for after the rules for your site are processed.
What you probably want is to set an upstream directive:
upstream flask_server {
server 127.0.0.1:666;
}
server {
...
location /server2 {
proxy_pass http://flask_server;
}
}

How to instantly display a custom page in nginx when upstream web server is down?

I tried to do this but for some reason it does work as expected:
server {
...
location / {
if (!-f /opt/jira/work/catalina.pid) {
return 503;
}
proxy_pass http://127.0.0.1:8080;
}
It seems that the file test doesn't work because it will return 503 even if the file exists on disk.
I want to be able to display an error page when the upstream webserver is not responding but without waiting for this too much. It should respond instantly if there is nothing running on port 8080.
Probably the file does not accessible to nginx worker. You should check permissions.

Resources